diff --git a/CHANGELOG.md b/CHANGELOG.md index e08673d..c725984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,24 @@ released. ## [Unreleased] -- Documentation +## [0.10.2] - 2024.09.11 +### Added + +- Support for LLVM 17/18 +- GenMC now warns when memory is not freed +- Minor performance improvements +- Landing page for doxygen + rudimentary development documentation + +### Changed + +- `__VERIFIER_assume()` and `__VERIFIER_spin_end()` now take a boolean argument (instead of int) +- GenMC now uses the new LLVM pass manager +- IMM performance may incur a minor penalty +- Project layout under `src` + +### Fixes + +- Minor bug fixes ## [0.10.1] - 2024.02.22 ### Fixes diff --git a/Makefile.am b/Makefile.am index d049373..d3cc913 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,92 +24,72 @@ nobase_genmc_HEADERS = \ noinst_LIBRARIES = libgenmc.a libgenmc_a_SOURCES = \ - src/ASize.cpp src/ASize.hpp \ - src/BisimilarityCheckerPass.cpp src/BisimilarityCheckerPass.hpp \ - src/Bitmask.hpp \ - src/BoundDecider.cpp src/BoundDecider.hpp \ - src/CallInfoCollectionPass.cpp src/CallInfoCollectionPass.hpp \ - src/CodeCondenserPass.cpp src/CodeCondenserPass.hpp \ - src/ContextBoundDecider.cpp src/ContextBoundDecider.hpp \ - src/Calculator.hpp \ - src/CallInstWrapper.hpp \ - src/ConfirmationAnnotationPass.cpp src/ConfirmationAnnotationPass.hpp \ - src/Config.cpp src/Config.hpp \ - src/DeclareInternalsPass.cpp src/DeclareInternalsPass.hpp \ - src/DefineLibcFunsPass.cpp src/DefineLibcFunsPass.hpp \ - src/DepExecutionGraph.cpp src/DepExecutionGraph.hpp \ - src/DepInfo.cpp src/DepInfo.hpp \ - src/DepTracker.hpp \ - src/DepView.cpp src/DepView.hpp \ - src/DriverFactory.hpp \ - src/EliminateAnnotationsPass.cpp src/EliminateAnnotationsPass.hpp \ - src/EliminateCASPHIsPass.cpp src/EliminateCASPHIsPass.hpp \ - src/EliminateCastsPass.cpp src/EliminateCastsPass.hpp \ - src/EliminateRedundantInstPass.cpp src/EliminateRedundantInstPass.hpp \ - src/EliminateUnusedCodePass.cpp src/EliminateUnusedCodePass.hpp \ - src/Error.hpp \ - src/EscapeCheckerPass.cpp src/EscapeCheckerPass.hpp \ - src/Event.cpp src/Event.hpp \ - src/EventAttr.hpp \ - src/EventLabel.cpp src/EventLabel.hpp \ - src/Execution.cpp \ - src/ExecutionGraph.cpp src/ExecutionGraph.hpp \ - src/ExternalFunctions.cpp \ - src/FunctionInlinerPass.cpp src/FunctionInlinerPass.hpp \ - src/GenMCDriver.cpp src/GenMCDriver.hpp \ - src/GraphIterators.hpp \ - src/IMMDriver.cpp src/IMMDriver.hpp \ - src/InstAnnotator.cpp src/InstAnnotator.hpp \ - src/Interpreter.cpp Interpreter.h \ - src/InterpreterEnumAPI.cpp src/InterpreterEnumAPI.hpp \ - src/IntrinsicLoweringPass.cpp src/IntrinsicLoweringPass.hpp \ - src/LabelVisitor.hpp \ - src/LoadAnnotationPass.cpp src/LoadAnnotationPass.hpp \ - src/LocalSimplifyCFGPass.cpp src/LocalSimplifyCFGPass.hpp \ - src/Logger.hpp \ - src/LLVMModule.cpp src/LLVMModule.hpp \ - src/LLVMUtils.cpp src/LLVMUtils.hpp \ - src/LoopUnrollPass.cpp src/LoopUnrollPass.hpp \ - src/LoopJumpThreadingPass.cpp src/LoopJumpThreadingPass.hpp \ - src/Matrix2D.hpp Matrix2D.tcc \ - src/MaximalIterator.hpp \ - src/MDataCollectionPass.hpp src/MDataCollectionPass.cpp \ - src/MemAccess.hpp \ - src/MMDetectorPass.cpp src/MMDetectorPass.hpp \ - src/ModuleID.hpp \ - src/ModuleInfo.cpp src/ModuleInfo.hpp \ - src/NameInfo.cpp src/NameInfo.hpp \ - src/Parser.cpp src/Parser.hpp \ - src/PromoteMemIntrinsicPass.cpp src/PromoteMemIntrinsicPass.hpp \ - src/PropagateAssumesPass.cpp src/PropagateAssumesPass.hpp \ - src/RADriver.cpp src/RADriver.hpp \ - src/RC11Driver.cpp src/RC11Driver.hpp \ - src/Revisit.cpp src/Revisit.hpp \ - src/RoundBoundDecider.cpp src/RoundBoundDecider.hpp \ - src/SAddr.cpp src/SAddr.hpp \ - src/SAddrAllocator.hpp \ - src/SCDriver.cpp src/SCDriver.hpp \ - src/SExpr.tcc src/SExpr.hpp \ - src/SExprVisitor.tcc src/SExprVisitor.hpp \ - src/Stamp.cpp src/Stamp.hpp \ - src/SVal.cpp src/SVal.hpp \ - src/SpinAssumePass.cpp src/SpinAssumePass.hpp \ - src/WBIterator.hpp \ - src/ThreadInfo.hpp \ - src/ThreadPinner.cpp src/ThreadPinner.hpp \ - src/ThreadPool.cpp src/ThreadPool.hpp \ - src/TSODriver.cpp src/TSODriver.hpp \ - src/WorkSet.hpp src/WorkSet.cpp \ - src/value_ptr.hpp \ - src/Verbosity.hpp src/Verbosity.cpp \ - src/VectorClock.hpp src/VectorClock.cpp \ - src/VerificationError.hpp src/VerificationError.cpp \ - src/View.hpp src/View.cpp \ - src/VSet.hpp src/VSet.tcc + src/ADT/DepView.cpp \ + src/ADT/VectorClock.cpp \ + src/ADT/View.cpp \ + src/Config/Config.cpp \ + src/Config/Verbosity.cpp \ + src/ExecutionGraph/DepExecutionGraph.cpp \ + src/ExecutionGraph/DepInfo.cpp \ + src/ExecutionGraph/Event.cpp \ + src/ExecutionGraph/EventLabel.cpp \ + src/ExecutionGraph/ExecutionGraph.cpp \ + src/ExecutionGraph/Stamp.cpp \ + src/Runtime/Execution.cpp \ + src/Runtime/ExternalFunctions.cpp \ + src/Runtime/Interpreter.cpp \ + src/Runtime/InterpreterEnumAPI.cpp \ + src/Static/LLVMModule.cpp \ + src/Static/LLVMUtils.cpp \ + src/Static/ModuleInfo.cpp \ + src/Static/Transforms/BisimilarityCheckerPass.cpp \ + src/Static/Transforms/CallInfoCollectionPass.cpp \ + src/Static/Transforms/CodeCondenserPass.cpp \ + src/Static/Transforms/ConfirmationAnnotationPass.cpp \ + src/Static/Transforms/DeclareInternalsPass.cpp \ + src/Static/Transforms/DefineLibcFunsPass.cpp \ + src/Static/Transforms/EliminateAnnotationsPass.cpp \ + src/Static/Transforms/EliminateCASPHIsPass.cpp \ + src/Static/Transforms/EliminateCastsPass.cpp \ + src/Static/Transforms/EliminateRedundantInstPass.cpp \ + src/Static/Transforms/EliminateUnusedCodePass.cpp \ + src/Static/Transforms/EscapeCheckerPass.cpp \ + src/Static/Transforms/FunctionInlinerPass.cpp \ + src/Static/Transforms/InstAnnotator.cpp \ + src/Static/Transforms/IntrinsicLoweringPass.cpp \ + src/Static/Transforms/LoadAnnotationPass.cpp \ + src/Static/Transforms/LocalSimplifyCFGPass.cpp \ + src/Static/Transforms/LoopJumpThreadingPass.cpp \ + src/Static/Transforms/LoopUnrollPass.cpp \ + src/Static/Transforms/MDataCollectionPass.cpp \ + src/Static/Transforms/MMDetectorPass.cpp \ + src/Static/Transforms/PromoteMemIntrinsicPass.cpp \ + src/Static/Transforms/PropagateAssumesPass.cpp \ + src/Static/Transforms/SpinAssumePass.cpp \ + src/Support/ASize.cpp \ + src/Support/NameInfo.cpp \ + src/Support/Parser.cpp \ + src/Support/SAddr.cpp \ + src/Support/SVal.cpp \ + src/Support/ThreadPinner.cpp \ + src/Support/ThreadPool.cpp \ + src/Verification/GenMCDriver.cpp \ + src/Verification/WorkSet.cpp \ + src/Verification/VerificationError.cpp \ + src/Verification/Revisit.cpp \ + src/Verification/Consistency/BoundDecider.cpp \ + src/Verification/Consistency/ContextBoundDecider.cpp \ + src/Verification/Consistency/IMMDriver.cpp \ + src/Verification/Consistency/RADriver.cpp \ + src/Verification/Consistency/RC11Driver.cpp \ + src/Verification/Consistency/RoundBoundDecider.cpp \ + src/Verification/Consistency/SCDriver.cpp \ + src/Verification/Consistency/TSODriver.cpp \ + src/main.cpp TESTS=scripts/fast-driver.sh scripts/randomize-driver.sh -AM_CXXFLAGS = -DINCLUDE_DIR=\"$(pkgincludedir)/$(pkg)/include\" -DSRC_INCLUDE_DIR=\"$(abs_top_srcdir)/include\" $(COVERAGE_CXXFLAGS) +AM_CXXFLAGS = -I$(abs_top_srcdir)/src -DINCLUDE_DIR=\"$(pkgincludedir)/$(pkg)/include\" -DSRC_INCLUDE_DIR=\"$(abs_top_srcdir)/include\" $(COVERAGE_CXXFLAGS) bin_PROGRAMS = genmc genmc_SOURCES = src/main.cpp genmc_LDADD = libgenmc.a -lpthread $(COVERAGE_LDFLAGS) diff --git a/README.md b/README.md index 309d6ca..f74a863 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ -GenMC +GenMC: Generic Model Checking for C Programs ===== -Generic Model Checking for C Programs -------------------------------------- GenMC is a stateless model checker for C programs that works on the level of LLVM Intermediate Representation. @@ -90,7 +88,7 @@ For a default build issue: ./genmc [options] -* For more detailed usage examples please refer to the [manual](doc/manual.pdf). +* For more detailed usage examples please refer to the [manual](doc/manual.md). Troubleshooting diff --git a/configure.ac b/configure.ac index ff7fff2..9aa1e93 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([GenMC], [0.10.1], [michalis@mpi-sws.org], [genmc], [https://plv.mpi-sws.org/genmc]) +AC_INIT([GenMC], [0.10.2], [michalis@mpi-sws.org], [genmc], [https://plv.mpi-sws.org/genmc]) m4_include([m4/ax_llvm.m4]) m4_include([m4/ax_clang.m4]) diff --git a/doc/Doxyfile b/doc/Doxyfile index 5d1499b..8e537af 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -906,7 +906,10 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = $(SRCDIR)/src +INPUT = $(SRCDIR)/src \ + $(SRCDIR)/README.md \ + $(SRCDIR)/doc/manual.md \ + $(SRCDIR)/doc/development.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -1104,7 +1107,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = $(SRCDIR)/README.md #--------------------------------------------------------------------------- # Configuration options related to source browsing diff --git a/doc/development.md b/doc/development.md new file mode 100644 index 0000000..28617d3 --- /dev/null +++ b/doc/development.md @@ -0,0 +1,25 @@ +# Modifying GenMC + +## Adding new label types + +To add a new label, follow these steps: + +1. Add a number and a name for the new label in Instruction.def +2. Add a class for the new label in ExecutionGraph/EventLabel.hpp. + Macros are provided for dummy labels and standard subclasses +3. Add a case for the new label in LabelVisitor.hpp +4. Define how the label should be printed in EventLabel.cpp + (optionally: LabelPrinterBase too) +5. Create a handler for the new label in GenMCDriver.{hpp,cpp} + (if necessary), and at DriverHandlerDispatcher +6. In case a new LLVM-IR function leads to the creation of + the new label: + - Add a number and a name for the internal function in + Runtime/InternalFunction.def. + - Define a function that dispatches the driver at + Runtime/Execution.cpp + +*Note:* the procedure above describes the bare minimum, and works well +for dummy labels or subclasses of existing labels. If e.g., the new +label has attributes like location then extra changes might be +required to ensure that iterators, etc still work. diff --git a/doc/manual.md b/doc/manual.md new file mode 100644 index 0000000..8b4c14b --- /dev/null +++ b/doc/manual.md @@ -0,0 +1,1150 @@ + +# Table of Contents + +1. [Introduction ](#org795e6fb) +2. [Basic Usage](#org700fd27) + 1. [A First Example](#org7e27d8c) + 2. [Reducing the State Space of a Program With `assume()` Statements ](#orgb09a697) + 3. [Handling Infinite Loops ](#org4c56a6b) + 4. [Error Reporting ](#org9d91cfd) +3. [Tool Features ](#org0589613) + 1. [Available Memory Models ](#org7cc84c4) + 1. [Note on LKMM Support](#orgc9035a4) + 2. [Note on Language Memory Models vs Hardware Memory Models](#org840ad38) + 2. [Race Detection and Memory Errors](#org3d3b7e5) + 3. [Lock-Aware Partial Order Reduction (LAPOR)](#orgf6357b1) + 4. [Barrier-Aware Model Checking (BAM)](#org20cc1f4) + 5. [Symmetry Reduction](#orga4022a7) + 6. [Checking Liveness ](#org8879883) + 7. [System Calls and Persistency Checks (Persevere) ](#orgf475797) + 1. [Consistency of File-Manipulating Programs](#orgc7d221d) + 2. [Persistency of File-Manipulating Programs](#org1ddc7c7) +4. [Command-line Options ](#org2b0335c) +5. [Supported APIs ](#org7e9d263) + 1. [Supported `stdio`, `unistd` and `fcntl` API](#org3ec10dd) + 2. [Supported `stdlib` API](#org55d405b) + 3. [Supported `pthread` API](#orgac7c1f9) + 4. [Supported SV-COMP (SV-COMP 2019) API](#org09067a4) +6. [Contact ](#org77d7590) + + + + + +# Introduction + +GenMC is an effective stateless model checker for programs +written under the RC11 (Lahav et al. 2017), IMM +(Podkopaev, Lahav, and Vafeiadis 2019), and LKMM (Alglave et al. 2018) memory models. +GenMC verifies safety properties of C programs that use `C11` +atomics and the `pthread` library for concurrency. It employs a very +effective dynamic partial order reduction technique +(Kokologiannakis, Raad, and Vafeiadis 2019a, 2022) that is +sound, complete and optimal. + +GenMC works at the level of LLVM Intermediate Representation (LLVM-IR) +and uses `clang` to translate C programs to LLVM-IR. This means it +can miss some bugs that are removed during the translation to LLVM-IR, +but it is guaranteed to encounter at least as many bugs as the +compiler backend will encounter. + +GenMC should compile on Linux and Mac OSX provided that the relevant +dependencies are installed. + + + + +# Basic Usage + +A generic invocation of GenMC resembles the following: + + genmc [OPTIONS] -- [CFLAGS] + +In the above command, `OPTIONS` include several options that can be +passed to GenMC (see Section [4](#org53d284e) for more details), and +`CFLAGS` are the options that one would normally pass to the C +compiler. If no such flags exist, the `--` can be omitted. +Lastly, `file` should be a C file that uses the `stdatomic.h` +and `pthread.h` APIs for concurrency. + +Note that, in order for GenMC to be able to verify it, `file` +needs to meet two requirements: finiteness and data-determinism. +Finiteness means that all tests need to have finite traces, +i.e., no infinite loops (these need to be bounded; see +Section [2.3](#orgaa0e9d1)). Data-determinism means that +the code under test should be data-deterministic, i.e., +not perform actions like calling `rand()`, performing +actions based on user input or the clock, etc. In other words, +all non-determinism should originate either from the scheduler +or the underlying (weak) memory model. + +As long as these requirements as satisfied, GenMC will detect safety +errors, races on non-atomic variables, as well as some memory errors +(e.g., double-free error). Users can provide safety specifications for +their programs by using `assert()` statements. + + + + +## A First Example + +Consider the following program, demonstrating the Message-Passing (MP) +idiom: + + /* file: mp.c */ + #include + #include + #include + #include + #include + + atomic_int data; + atomic_bool ready; + + void *thread_1(void *unused) + { + atomic_store_explicit(&data, 42, memory_order_relaxed); + atomic_store_explicit(&ready, true, memory_order_release); + return NULL; + } + + void *thread_2(void *unused) + { + if (atomic_load_explicit(&ready, memory_order_acquire)) { + int d = atomic_load_explicit(&data, memory_order_relaxed); + assert(d == 42); + } + return NULL; + } + + int main() + { + pthread_t t1, t2; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_2, NULL)) + abort(); + + return 0; + } + +In order to analyze the code above with GenMC, we can use the +following command: + + genmc mp.c + +with which GenMC will yield the following result: + + Number of complete executions explored: 2 + Total wall-clock time: 0.02s + +GenMC explores two executions: one where $ready = data =0$, and +one where $ready = data = 1$. + + + + +## Reducing the State Space of a Program With `assume()` Statements + +In some programs, we only care about what happens when certain reads +read certain values of interest. That said, by default, GenMC +will explore all possible values for all program loads, possibly +leading to the exploration of an exponential number of executions. + +To alleviate this problem, GenMC supports the +`__VERIFIER_assume()` function (similar to the one specified in +SV-COMP (SV-COMP 2019)). This function takes an integer argument +(e.g., the value read from a load), and only continues the execution +if the argument is non-zero. + +For example, let us consider the MP program from the previous section, +and suppose that we are only interested in verifying the assertion +in cases where the first read of the second thread reads 1. We can +use an `assume()` statement to achieve this, as shown below: + + /* file: mp-assume.c */ + #include + #include + #include + #include + #include + + void __VERIFIER_assume(int); + + atomic_int data; + atomic_bool ready; + + void *thread_1(void *unused) + { + atomic_store_explicit(&data, 42, memory_order_relaxed); + atomic_store_explicit(&ready, true, memory_order_release); + return NULL; + } + + void *thread_2(void *unused) + { + int r = atomic_load_explicit(&ready, memory_order_acquire); + __VERIFIER_assume(r); + if (r) { + int d = atomic_load_explicit(&data, memory_order_relaxed); + assert(d == 42); + } + return NULL; + } + + int main() + { + pthread_t t1, t2; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_2, NULL)) + abort(); + + return 0; + } + +Note that the `__VERIFIER_assume()` function has to be declared. Alternatively, +one can include the `` header, that contains the declarations for all +the special function that GenMC offers (see Section [5](#org801c94c)). + +If we run GenMC on the `mp-assume.c` program above, we get the following +output: + + Number of complete executions explored: 1 + Number of blocked executions seen: 1 + Total wall-clock time: 0.02s + +As can be seen, GenMC only explored one full execution (the one +where $r = 1$, while the execution where $r = 0$ was blocked, because +of the `assume()` statement. Of course, while the usage of `assume()` +does not make any practical difference in this small example, this is +not always the case: generally, using `assume()` might yield an +exponential improvement in GenMC's running time. + +Finally, note that, when using GenMC under memory models that +track dependencies (see Section [3.1](#org0b70d16)), an `assume()` +statement will introduce a control dependency in the program code. + + + + +## Handling Infinite Loops + +As mentioned in the beginning of this section, all programs that +GenMC can handle need to have finite traces. That said, many +programs of interest do not fulfill this requirement, because, for +example, they have some infinite loop. GenMC offers three +solutions for such cases. + +First, GenMC can automatically perform the "spin-assume" +transformation for a large class of spinloops. Specifically, as long +as a spinloop completes a full iteration with no visible side effects +(e.g., stores to global variables), GenMC will cut the respective +execution. For instance, consider the following simple loop: + + int r = 0; + while (!atomic_compare_exchange_strong(&x, &r, 1)) + r = 0; + +Since this loop has no visible side-effects whenever it completes +a full iteration, GenMC will not explore more than one +execution where the loop fails (the execution where the loop fails +will be reported as a blocked execution). The "spin-assume" +transformation has proven to be very effective for a wide range of +loops; for more details on whether it applies on a specific loop, +please see (Kokologiannakis, Ren, and Vafeiadis 2021). + +Finally, for infinite loops with side effects, we can use the +`-unroll=N` command-line option (see Section [4](#org53d284e)). This option +bounds all loops so that they are executed at most `N` times. In this +case, any verification guarantees that GenMC provides hold up to +that bound. If you are unsure whether you should use the `-unroll=N` +switch, you can try to verify the program and check whether +GenMC complains about the graph size +(`-warn-on-graph-size=`). If it does, there is a good chance you +need to use the `-unroll=N` switch. + +Note that the loop-bounding happens at the LLVM-IR level, which means +that the loops there may not directly correspond to loops in the C +code (depending on the enabled compiled optimizations, etc). + + + + +## Error Reporting + +In the previous sections, saw how GenMC verifies the small MP program. +Let us now proceed with an erroneous version of this program, in order +to show how GenMC reports errors to the user. + +Consider the following variant of the MP program below, where the +store to `ready` in the first thread is now performed using a relaxed +access: + + /* file: mp-error.c */ + #include + #include + #include + #include + #include + + atomic_int data; + atomic_bool ready; + + void *thread_1(void *unused) + { + atomic_store_explicit(&data, 42, memory_order_relaxed); + atomic_store_explicit(&ready, true, memory_order_relaxed); + return NULL; + } + + void *thread_2(void *unused) + { + if (atomic_load_explicit(&ready, memory_order_acquire)) { + int d = atomic_load_explicit(&data, memory_order_relaxed); + assert(d == 42); + } + return NULL; + } + + int main() + { + pthread_t t1, t2; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_2, NULL)) + abort(); + + return 0; + } + +This program is buggy since the load from `ready` no longer +synchronizes with the corresponding store, which in turn means that +the load from `data` may also read 0 (the initial value), and +not just 42. + +Running GenMC on the above program, we get the following outcome: + + Error detected: Safety violation! + Event (2, 2) in graph: + <-1, 0> main: + (0, 0): B + (0, 1): M + (0, 2): M + (0, 3): TC [forks 1] L.30 + (0, 4): Wna (t1, 1) L.30 + (0, 5): TC [forks 2] L.32 + (0, 6): Wna (t2, 2) L.32 + (0, 7): E + <0, 1> thread_1: + (1, 0): B + (1, 1): Wrlx (data, 42) L.12 + (1, 2): Wrlx (ready, 1) L.13 + (1, 3): E + <0, 2> thread_2: + (2, 0): B + (2, 1): Racq (ready, 1) [(1, 2)] L.19 + (2, 2): Rrlx (data, 0) [INIT] L.20 + + Assertion violation: d == 42 + Number of complete executions explored: 1 + Total wall-clock time: 0.02s + +GenMC reports an error and prints some information relevant for +debugging. First, it prints the type of the error, then the execution +graph representing the erroneous execution, and finally the error +message, along with the executions explored so far and the time that +was required. + +The graph contains the events of each thread along with some +information about the corresponding source-code instructions. For +example, for write events (e.g., event (1, 1)), the access mode, the +name of the variable accessed, the value written, as well as the +corresponding source-code line are printed. The situation is similar +for reads (e.g., event (2, 1)), but also the position in the graph +from which the read is reading from is printed. + +Note that there are many different types of events. However, many of +them are GenMC-related and not of particular interest to users (e.g., +events labeled with \`B', which correspond to the beginning of a +thread). Thus, GenMC only prints the source-code lines for events +that correspond to actual user instructions, thus helping the +debugging procedure. + +Finally, when more information regarding an error are required, +two command-line switches are provided. The `-dump-error-graph=` +switch provides a visual representation of the erroneous execution, +as it will output the reported graph in DOT format in ``, +so that it can be viewed by a PDF viewer. Finally, the `-print-error-trace` +switch will print a sequence of source-code lines leading to +the error. The latter is especially useful for cases where +the bug is not caused by some weak-memory effect but rather from +some particular interleaving (e.g., if all accesses are + `memory_order_seq_cst`), and the write where each read is reading +from can be determined simply by locating the previous write in the +same memory location in the sequence. + + + + +# Tool Features + + + + +## Available Memory Models + +By default, GenMC verifies programs under RC11. However, apart +from RC11, GenMC also supports IMM and (experimentally) LKMM. +The difference between these memory models (as far as allowed outcomes are concerned) +can be seen in the following program: + + /* file: lb.c */ + #include + #include + #include + #include + #include + + atomic_int x; + atomic_int y; + + void *thread_1(void *unused) + { + int a = atomic_load_explicit(&x, memory_order_relaxed); + atomic_store_explicit(&y, 1, memory_order_relaxed); + return NULL; + } + + void *thread_2(void *unused) + { + int b = atomic_load_explicit(&y, memory_order_relaxed); + atomic_store_explicit(&x, 1, memory_order_relaxed); + return NULL; + } + + int main() + { + pthread_t t1, t2; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_2, NULL)) + abort(); + + return 0; + } + +Under RC11, an execution where both $a = 1$ and $b = 1$ is forbidden, +whereas such an execution is allowed under IMM and LKMM. To account for such +behaviors, GenMC tracks dependencies between program instructions +thus leading to a constant overhead when verifying programs under +models like IMM. + + + + +### Note on LKMM Support + +GenMC's support for LKMM is currently at an experimental stage. +GenMC includes plain accesses in ppo +(in contrast to what (Alglave et al. 2018) dictates), as plain accesses +to temporary LLVM-IR variables are occasionally generated by `clang` between +accesses to shared memory, and thus including them in ppo is +necessary to preserve dependencies. + +Tests that use LKMM atomics need to include ` + +### Note on Language Memory Models vs Hardware Memory Models + +RC11 is a language-level memory model while IMM is a hardware memory +model. Subsequently, the verification results produced by GenMC +for the two models should be interpreted somewhat differently. + +What this means in practice is that, when verifying programs under +RC11, the input file is assumed to be the very source code the user +wrote. A successful verification result under RC11 holds all the +way down to the actual executable, due to the guarantees provided +by RC11 (Lahav et al. 2017). + +On the other hand, when verifying programs under IMM, the input file +is assumed to be the assembly code run by the processor (or, more +precisely, a program in IMM's intermediate language). And while +GenMC allows the input file to be a C file (as in the case of +RC11), it assumes that this C file corresponds to an assembly file +that is the result of the compilation of some program in IMM's +language. In other words, program correctness is not preserved across +compilation for IMM inputs. + + + + +## Race Detection and Memory Errors + +For memory models that define the notion of a race, GenMC will +report executions containing races erroneous. For instance, under +RC11, the following program is racy, as there is no happens-before +between the write of $x$ in the first thread and the non-atomic +read of $x$ in the second thread (even though the latter causally +depends on the former). + + /* file: race.c */ + #include + #include + #include + #include + #include + + atomic_int x; + + void *thread_1(void *unused) + { + atomic_store_explicit(&x, 1, memory_order_relaxed); + return NULL; + } + + void *thread_2(void *unused) + { + int a, b; + + a = atomic_load_explicit(&x, memory_order_relaxed); + if (a == 1) + b = *((int *) &x); + return NULL; + } + + int main() + { + pthread_t t1, t2; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_2, NULL)) + abort(); + + return 0; + } + +Additionally, for all memory models, GenMC detects some memory +races like accessing memory that has been already freed, accessing +dynamic memory that has not been allocated, or freeing an already +freed chunk of memory. + +Race detection can be completely disabled by means of +`-disable-race-detection`, which may yield better performance for +certain programs. + + + + +## Lock-Aware Partial Order Reduction (LAPOR) + +For programs that employ coarse-grained locking schemes LAPOR +(Kokologiannakis, Raad, and Vafeiadis 2019b) might greatly reduce the state space +and thus the verification time. For instance, consider the following +program where a lock is used (overly conservatively) to read a shared +variable: + + /* file: lapor.c */ + #include + #include + #include + #include + #include + + #ifndef N + # define N 2 + #endif + + pthread_mutex_t l; + int x; + + void *thread_n(void *unused) + { + pthread_mutex_lock(&l); + int r = x; + pthread_mutex_unlock(&l); + return NULL; + } + + int main() + { + pthread_t t[N]; + + for (int i = 0; i < N; i++) { + if (pthread_create(&t[i], NULL, thread_n, NULL)) + abort(); + } + + return 0; + } + +Running GenMC on the program above results in the following outcome: + + Number of complete executions explored: 2 + Total wall-clock time: 0.02s + +As expected, as the value of $N$ increases, the executions of the +program also increase in an exponential manner. + +However, if we run GenMC with `-lapor` on the same program, we get the +following output: + + Number of complete executions explored: 1 + Total wall-clock time: 0.02s + +LAPOR leverages the fact that the contents of the critical +sections of the threads commute (i.e., the order in which the critical +sections are executed does not matter), and only explores 1 execution +for all values of $N$. + +We note that for programs where no further reduction in the +state space is possible, LAPOR can be cause a polynomial +slowdown. + + + + +## Barrier-Aware Model Checking (BAM) + +GenMC v0.6 comes with built-in support for `pthread_barrier_t` +functions (see Section [5](#org801c94c)) via BAM (Kokologiannakis and Vafeiadis 2021). +As an example of BAM in action, consider the following program: + + /* file: bam.c */ + #include + #include + #include + #include + #include + #include + + #ifndef N + # define N 2 + #endif + + pthread_barrier_t b; + atomic_int x; + + void *thread_n(void *unused) + { + ++x; + pthread_barrier_wait(&b); + assert(x == N); + return NULL; + } + + int main() + { + pthread_t t[N]; + + pthread_barrier_init(&b, NULL, N); + for (int i = 0u; i < N; i++) { + if (pthread_create(&t[i], NULL, thread_n, NULL)) + abort(); + } + + return 0; + } + +Running GenMC on the program above results in the following output: + + Number of complete executions explored: 2 + Total wall-clock time: 0.01s + +As can be seen, GenMC treats `barrier_wait` calls as no-ops, +and they do not lead to any additional explorations. (The two executions +explored correspond to the possible ways in which `x` can be incremented). + +However, if we disable BAM by means of the `-disable-bam` switch, +get get the following output: + + Number of complete executions explored: 4 + Number of blocked executions seen: 4 + Total wall-clock time: 0.01s + +Note that while BAM can lead to the exploration of exponentially +fewer executions, it can only be used if the result of the `barrier_wait` +is not used. If it is, then using `-disable-bam` is necessary, +as GenMC currently does not enforce this limitation. + + + + +## Symmetry Reduction + +GenMC also employs an experimental symmetry reduction mechanism. +While GenMC's symmetry reduction does not guarantee optimality, +i.e., might explore more executions than what an ideal symmetry +reduction algorithm would (although never more than what the enabled +partitioning dictates), it is still beneficial to use when threads +use the same code. + +For instance, if `-sr` is used in the following program, GenMC +explores only one execution instead of 6. + + /* file: sr.c */ + #include + #include + #include + #include + #include + #include + + atomic_int x; + + void *thread_n(void *unused) + { + ++x; + return NULL; + } + + int main() + { + pthread_t t1, t2, t3; + + if (pthread_create(&t1, NULL, thread_n, NULL)) + abort(); + if (pthread_create(&t2, NULL, thread_n, NULL)) + abort(); + if (pthread_create(&t3, NULL, thread_n, NULL)) + abort(); + + return 0; + } + +In order for symmetry reduction to actually take place, the spawned +threads need to share exactly the same code, have exactly the same +arguments, and also there must not be any memory access (at the +LLVM-IR level) between the spawn instructions. + + + + +## Checking Liveness + +GenMC can also check for liveness violations in programs with +spinloops. Consider the following simple program: + + /* file: liveness.c */ + #include + #include + #include + + atomic_int x; + + void *thread_1(void *unused) + { + while (!x) + ; + return NULL; + } + + int main() + { + pthread_t t1; + + if (pthread_create(&t1, NULL, thread_1, NULL)) + abort(); + + return 0; + } + +Since there are no writes to $x$, the loop in `thread_1` above +will never terminate. Indeed, running GenMC with + `-check-liveness` produces a relevant error report: + + Error detected: Liveness violation! + Event (1, 4) in graph: + <-1, 0> main: + (0, 0): B + (0, 1): TC [forks 1] L.19 + (0, 2): E + <0, 1> thread_1: + (1, 0): B + (1, 1): LOOP_BEGIN + (1, 2): SPIN_START + (1, 3): Rsc (x, 0) [INIT] L.9 + (1, 4): BLOCK [spinloop] + + Non-terminating spinloop: thread 1 + Number of complete executions explored: 0 + Number of blocked executions seen: 1 + Total wall-clock time: 0.07s + +The `-check-liveness` switch will automatically check for liveness +violations in all loops that have been captured by the spin-assume +transformation (see [4](#org53d284e)). + + + + +## System Calls and Persistency Checks (Persevere) + +Since v0.5, GenMC supports the verification programs involving +system calls for file manipulation like `read()` and `write()`. In +addition, using Persevere (Kokologiannakis et al. 2021), +GenMC can verify persistency properties of such programs. Below +we discuss some details that are important when it comes to verifying +programs that involve file manipulation. + + + + +### Consistency of File-Manipulating Programs + +As a first example consider the program below, where a file +`"foo.txt"` is first populated by `main`, and then concurrently +read and written by two threads at offset 0: + + /* file: file-rw.c */ + #include + #include + #include + #include + #include + #include + #include + + void *thread_1(void *fdp) + { + int fd = *((int *) fdp); + char buf[8]; + + buf[0] = buf[1] = 1; + int nw = pwrite(fd, buf, 2, 0); + return NULL; + } + + void *thread_2(void *fdp) + { + int fd = *((int *) fdp); + char buf[8]; + + int nr = pread(fd, buf, 2, 0); + if (nr == 2) + assert((buf[0] == 0 && buf[1] == 0) || (buf[0] == 1 && buf[1] == 1)); + return NULL; + } + + int main() + { + pthread_t t1, t2; + char buf[8]; + + int fd = open("foo.txt", O_CREAT|O_RDWR, 0); + + buf[0] = buf[1] = 0; + int nw = write(fd, buf, 2); + assert(nw == 2); + + if (pthread_create(&t1, NULL, thread_1, &fd)) + abort(); + if (pthread_create(&t2, NULL, thread_2, &fd)) + abort(); + + if (pthread_join(t1, NULL)) + abort(); + if (pthread_join(t2, NULL)) + abort(); + + return 0; + } + +One property we might be interested in in the above program is whether +the reading thread can see any other (intermediate) state for the file +apart from `00` and `11`. Indeed, as can be seen below, running GenMC +on the program above produces an example where the assertion is violated. + + Error detected: Safety violation! + [...] + Assertion violation: (buf[0] == 0 && buf[1] == 0) || (buf[0] == 1 && buf[1] == 1) + Number of complete executions explored: 1 + Total wall-clock time: 0.03s + +Apart from safety violations like in this case, GenMC will also +report system call failures as errors (e.g., trying to write to a file +that has been opened with `O_RDONLY`). This behavior can be disabled +with `-disable-stop-on-system-error`, which will make GenMC report +such errors through `errno`. + +When including headers like `stdio.h` or `unistd.h`, GenMC intercepts +calls to `open()`, `read()`, `write()`, and other system calls defined +in these header files, and models their behavior. Note that these header +files are also part of GenMC so, in general, only the functionality +described in Section [5](#org801c94c) from said header files can be used in programs. + +Note that only constant (static) strings can be used as filenames when +using system calls. The filenames need not exist as regular files in +the user's system, as the effects of these system calls are modeled, +and not actually executed. Thus, it is in general preferable if the +contents of the manipulated files maintain a small size across +executions. + + + + +### Persistency of File-Manipulating Programs + +In addition to checking whether safety properties of file-manipulating +programs with regards to consistency are satisfied (as described +above), GenMC can also check whether some safety property with +regards to persistency (under `ext4`) is satisfied. This is achieved +through Persevere, which can be enabled with `-persevere`. + +For example, let us consider the program below and suppose we want to +check whether, after a crash, it is possible to observe only a part of +an append to a file: + + /* file: pers.c */ + #include + #include + #include + #include + #include + #include + #include + + #include + #include + + void __VERIFIER_recovery_routine(void) + { + char buf[8]; + buf[0] = 0; + buf[1] = 0; + + int fd = open("foo.txt", O_RDONLY, 0666); + assert(fd != -1); + + /* Is is possible to read something other than {2,2} ? */ + int nr = pread(fd, buf, 2, 3); + if (nr == 2) + assert(buf[0] == 2 && buf[1] == 2); + return; + } + + int main() + { + char buf[8]; + + buf[0] = 1; + buf[1] = 1; + buf[2] = 1; + + int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, S_IRWXU); + write(fd, buf, 3); + + __VERIFIER_pbarrier(); + + write(fd, buf + 3, 2); + + close(fd); + + return 0; + } + +In the program above, the `__VERIFIER_pbarrier()` call ensures that +all the file operations before it will be considered as "persisted" +(i.e., having reached disk) in this program. The function +`__VERIFIER_recovery_routine()` is automatically called by GenMC +and contains the code to be run by the recovery routine, in order to +observe the post-crash disk state. + +In this case, by issuing `genmc -persevere pers.c` we observe that +partly observing the append is indeed possible under `ext4`, as can +be seen below. + + Error detected: Recovery error! + [...] + Assertion violation: buf[0] == 2 && buf[1] == 2 + Number of complete executions explored: 2 + Total wall-clock time: 0.08s + +For this program in particular, this property is violated due to the +default block size (which is 2 bytes), and the nature of appends in +the default data ordering mode of `ext4` (`data=ordered`). + +In general, such parameters of `ext4` can be tuned via the +`--block-size` and `--journal-data` switches (see Section [4](#org53d284e) and +`genmc -help` for more information). GenMC currently assumes a +sector size of 1 byte. + + + + +# Command-line Options + +A full list of the available command-line options can by viewed +by issuing `genmc -help`. Below we describe the ones that +are most useful when verifying user programs. + +- **`-rc11`:** Perform the exploration under the RC11 memory model (default) +- **`-imm`:** Perform the exploration under the IMM memory model +- **`-lkmm`:** Perform the exploration under the LKMM memory model (experimental) +- **`-wb`:** Perform the exploration based on the porf + equivalence partitioning. +- **`-mo`:** Perform the exploration based on the po $\cup$ rf $\cup$ mo + equivalence partitioning (default). +- **`-lapor`:** Enable Lock-Aware Partial Order Reduction (LAPOR) +- **`-disable-bam`:** Disables Barrier-Aware Model-checking (BAM) +- **`-check-liveness`:** Check for liveness violations in spinloops +- **`-persevere`:** Enable `ext4` persistency checks (Persevere) +- **`-unroll=`:** All loops will be executed at most $N$ times. +- **`-dump-error-graph=`:** Outputs an erroneous graph to file + ``. +- **`-print-error-trace`:** Outputs a sequence of source-code instructions + that lead to an error. +- **`-disable-race-detection`:** Disables race detection for non-atomic + accesses. +- **`-program-entry-function=`:** Uses function `` + as the program's entry point, instead of `main()`. +- **`-disable-spin-assume`:** Disables the transformation of spin loops to + `assume()` statements. + + + + +# Supported APIs + +Apart from C11 API (defined in `stdatomic.h`) and the `assert()` +function used to define safety specifications, below we list supported +functions from different libraries. + + + + +## Supported `stdio`, `unistd` and `fcntl` API + +The following functions are supported for I/O: + +- **`int printf(const char *, ...)`:** + +- **`int open (const char *, int , mode_t)`:** + +- **`int creat (const char *, mode_t)`:** + +- **`off_t lseek (int, off_t, int)`:** + +- **`int close (int)`:** + +- **`ssize_t read (int, void *, size_t)`:** + +- **`ssize_t write (int, const void *, size_t)`:** + +- **`ssize_t pread (int, void *, size_t, off_t)`:** + +- **`ssize_t pwrite (int, const void *, size_t, off_t)`:** + +- **`int truncate (const char *, off_t)`:** + +- **`int link (const char *, const char *)`:** + +- **`int unlink (const char *)`:** + +- **`int rename (const char *, const char *)`:** + +- **`int fsync (int)`:** + +- **`void sync (void)`:** + +Note that the functions above are modeled and not actually executed, +as described in Section [3.7](#org152be60). + + + + +## Supported `stdlib` API + +The following functions are supported from `stdlib.h`: + +- **`void abort(void)`:** + +- **`int abs(int)`:** + +- **`int atoi(const char *)`:** + +- **`void free(void *)`:** + +- **`void *malloc(size_t)`:** + +- **`void *aligned_alloc(size_t, size_t)`:** + + + + +## Supported `pthread` API + +The following functions are supported from `pthread.h`: + +- **`int pthread_create (pthread_t *, const pthread_attr_t *, void *(*) (void *), void *)`:** + +- **`int pthread_join (pthread_t, void **)`:** + +- **`pthread_t pthread_self (void)`:** + +- **`void pthread_exit (void *)`:** + +- **`int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *)`:** + +- **`int pthread_mutex_lock (pthread_mutex_t *)`:** + +- **`int pthread_mutex_trylock (pthread_mutex_t *)`:** + +- **`int pthread_mutex_unlock (pthread_mutex_t *)`:** + +- **`int pthread_mutex_destroy (pthread_mutex_t *)`:** + +- **`int pthread_barrier_init (pthread_barrier_t *, const pthread_barrierattr_t *, unsigned)`:** + +- **`int pthread_barrier_wait (pthread_barrier_t *)`:** + +- **`int pthread_barrier_destroy (pthread_barrier_t *)`:** + + + + +## Supported SV-COMP (SV-COMP 2019) API + +The following functions from the ones defined in SV-COMP (SV-COMP 2019) are supported: + +- **`void __VERIFIER_assume(int)`:** + +- **`int __VERIFIER_nondet_int(void)`:** + +Note that, since GenMC is a stateless model checker, `__VERIFIER_nondet_int()` +only "simulates" data non-determism, and does actually provide support for it. +More specifically, the sequence of numbers it produces for each thread, remains +the same across different executions. + + + + +# Contact + +For feedback, questions, and bug reports please send an e-mail to +[michalis@mpi-sws.org](mailto:michalis@mpi-sws.org). + +Alglave, Jade, Luc Maranget, Paul E. McKenney, Andrea Parri, and Alan Stern. 2018. “Frightening Small Children and Disconcerting Grown-Ups: Concurrency in the Linux Kernel.” In ASPLOS 2018, 405–18. Williamsburg, VA, USA: ACM. <10.1145/3173162.3177156>. + +Kokologiannakis, Michalis, and Viktor Vafeiadis. 2021. “BAM: Efficient Model Checking for Barriers.” In NETYS 2021. LNCS. Springer. <10.1007/978-3-030-91014-3_16>. + +Kokologiannakis, Michalis, Ilya Kaysin, Azalea Raad, and Viktor Vafeiadis. 2021. “PerSeVerE: Persistency Semantics for Verification under Ext4.” Proc. ACM Program. Lang. 5 (POPL). New York, NY, USA: ACM. <10.1145/3434324>. + +Kokologiannakis, Michalis, Azalea Raad, and Viktor Vafeiadis. 2019a. “Model Checking for Weakly Consistent Libraries.” In PLDI 2019. New York, NY, USA: ACM. <10.1145/3314221.3314609>. + +———. 2019b. “Effective Lock Handling in Stateless Model Checking.” Proc. ACM Program. Lang. 3 (OOPSLA). New York, NY, USA: ACM. <10.1145/3360599>. + +Kokologiannakis, Michalis, Xiaowei Ren, and Viktor Vafeiadis. 2021. “Dynamic Partial Order Reductions for Spinloops.” In FMCAD 2021, 163–72. IEEE. <10.34727/2021/isbn.978-3-85448-046-4\_25>. + +Lahav, Ori, Viktor Vafeiadis, Jeehoon Kang, Chung-Kil Hur, and Derek Dreyer. 2017. “Repairing Sequential Consistency in C/C++11.” In PLDI 2017, 618–32. Barcelona, Spain: ACM. <10.1145/3062341.3062352>. + +Podkopaev, Anton, Ori Lahav, and Viktor Vafeiadis. 2019. “Bridging the Gap between Programming Languages and Hardware Weak Memory Models.” Proc. ACM Program. Lang. 3 (POPL). New York, NY, USA: ACM: 69:1–69:31. <10.1145/3290382>. + +SV-COMP. 2019. “Competition on Software Verification (SV-COMP).” . diff --git a/include/genmc.h b/include/genmc.h index bc40584..aa382f3 100644 --- a/include/genmc.h +++ b/include/genmc.h @@ -1,6 +1,7 @@ #ifndef __GENMC_H__ #define __GENMC_H__ +#include #include #ifdef __cplusplus @@ -11,7 +12,7 @@ extern "C" /* * Blocks the current execution if the argument is false */ -void __VERIFIER_assume(int) __attribute__ ((__nothrow__)); +void __VERIFIER_assume(bool) __attribute__ ((__nothrow__)); /* * Models a limited amount of non-determinism by returning @@ -92,7 +93,7 @@ void __VERIFIER_join_symmetric (__VERIFIER_thread_t __th) */ void __VERIFIER_loop_begin(void) __attribute__ ((__nothrow__)); void __VERIFIER_spin_start(void) __attribute__ ((__nothrow__)); -void __VERIFIER_spin_end(int) __attribute__ ((__nothrow__)); +void __VERIFIER_spin_end(bool) __attribute__ ((__nothrow__)); /* * Marker function that denotes that a store is local. diff --git a/include/genmc_internal.h b/include/genmc_internal.h index c97b325..ae81c70 100644 --- a/include/genmc_internal.h +++ b/include/genmc_internal.h @@ -1,6 +1,7 @@ #ifndef __GENMC_INTERNAL_H__ #define __GENMC_INTERNAL_H__ +#include #include #include #include @@ -20,10 +21,14 @@ typedef struct { int __private; } __VERIFIER_attr_t; typedef struct { int __private; } __VERIFIER_barrier_t; typedef int __VERIFIER_barrierattr_t; +typedef struct { int __private; } __VERIFIER_cond_t; +typedef long __VERIFIER_condattr_t; + typedef struct { int __private; } __VERIFIER_mutex_t; typedef long __VERIFIER_mutexattr_t; #define __VERIFIER_MUTEX_INITIALIZER { 0 } +#define __VERIFIER_COND_INITIALIZER { 0 } typedef struct { void *__dummy; } __VERIFIER_hazptr_t; @@ -146,6 +151,19 @@ extern int __VERIFIER_mutex_lock (__VERIFIER_mutex_t *__mutex) __attribute__ ((_ extern int __VERIFIER_mutex_unlock (__VERIFIER_mutex_t *__mutex) __attribute__ ((__nothrow__)); +/* Condvar functions */ + +extern int __VERIFIER_cond_init (__VERIFIER_cond_t *__cond, + const __VERIFIER_condattr_t *__condattr) __attribute__ ((__nothrow__)); + +extern int __VERIFIER_cond_destroy (__VERIFIER_cond_t *__cond) __attribute__ ((__nothrow__)); + +extern int __VERIFIER_cond_wait (__VERIFIER_cond_t *__cond) __attribute__ ((__nothrow__)); + +extern int __VERIFIER_cond_signal (__VERIFIER_cond_t *__cond) __attribute__ ((__nothrow__)); + +extern int __VERIFIER_cond_bcast (__VERIFIER_cond_t *__cond) __attribute__ ((__nothrow__)); + /* barrier functions */ @@ -171,6 +189,8 @@ extern int __VERIFIER_barrier_destroy (__VERIFIER_barrier_t *__barrier) __attrib #define GENMC_KIND_SPECUL 0x00080000 #define GENMC_KIND_CONFIRM 0x00100000 +void __VERIFIER_assume(bool) __attribute__ ((__nothrow__)); + /* * Annotate a subsequent instruction with the given mask. */ diff --git a/include/pthread.h b/include/pthread.h index 6c94113..ecf9af6 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -32,8 +32,8 @@ extern "C" typedef __VERIFIER_attr_t pthread_attr_t; typedef __VERIFIER_barrier_t pthread_barrier_t; typedef __VERIFIER_barrierattr_t pthread_barrierattr_t; -/* typedef struct { int __private; } pthread_cond_t; */ -/* typedef long pthread_condattr_t; */ +/* typedef __VERIFIER_cond_t pthread_cond_t; */ +/* typedef __VERIFIER_condattr_t pthread_condattr_t; */ /* typedef int pthread_key_t; */ typedef __VERIFIER_mutex_t pthread_mutex_t; typedef __VERIFIER_mutexattr_t pthread_mutexattr_t; @@ -44,6 +44,7 @@ typedef __VERIFIER_mutexattr_t pthread_mutexattr_t; typedef __VERIFIER_thread_t pthread_t; #define PTHREAD_MUTEX_INITIALIZER __VERIFIER_MUTEX_INITIALIZER +#define PTHREAD_COND_INITIALIZER __VERIFIER_COND_INITIALIZER /* Detach state. */ enum @@ -502,27 +503,50 @@ int pthread_mutex_unlock(pthread_mutex_t *__mutex) /* /\* Initialize condition variable COND using attributes ATTR, or use */ /* the default values if later is NULL. *\/ */ -/* extern int pthread_cond_init (pthread_cond_t *__restrict __cond, */ -/* const pthread_condattr_t *__restrict __cond_attr) */ -/* ; */ +/* __attribute__ ((always_inline)) static inline */ +/* int pthread_cond_init(pthread_cond_t *__restrict __cond, */ +/* const pthread_condattr_t *__restrict __cond_attr) */ +/* { */ +/* __VERIFIER_cond_init(__cond, __cond_attr); */ +/* return 0; */ +/* } */ /* /\* Destroy condition variable COND. *\/ */ -/* extern int pthread_cond_destroy (pthread_cond_t *__cond) */ -/* ; */ +/* __attribute__ ((always_inline)) static inline */ +/* int pthread_cond_destroy(pthread_cond_t *__cond) */ +/* { */ +/* __VERIFIER_cond_destroy(__cond); */ +/* return 0; */ +/* } */ /* /\* Wake up one thread waiting for condition variable COND. *\/ */ -/* extern int pthread_cond_signal (pthread_cond_t *__cond) */ -/* ; */ +/* __attribute__ ((always_inline)) static inline */ +/* int pthread_cond_signal(pthread_cond_t *__cond) */ +/* { */ +/* __VERIFIER_cond_signal(__cond); */ +/* return 0; */ +/* } */ /* /\* Wake up all threads waiting for condition variables COND. *\/ */ -/* extern int pthread_cond_broadcast (pthread_cond_t *__cond) */ -/* ; */ +/* __attribute__ ((always_inline)) static inline */ +/* int pthread_cond_broadcast (pthread_cond_t *__cond) */ +/* { */ +/* __VERIFIER_cond_bcast(__cond); */ +/* return 0; */ +/* } */ /* /\* Wait for condition variable COND to be signaled or broadcast. */ /* MUTEX is assumed to be locked before. *\/ */ -/* extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, */ -/* pthread_mutex_t *__restrict __mutex) */ -/* ; */ +/* __attribute__ ((always_inline)) static inline */ +/* int pthread_cond_wait (pthread_cond_t *__restrict __cond, */ +/* pthread_mutex_t *__restrict __mutex) */ +/* { */ +/* pthread_mutex_unlock(__mutex); */ +/* int val = __VERIFIER_cond_wait(__cond); */ +/* __VERIFIER_assume(val > 0); */ +/* pthread_mutex_lock(__mutex); */ +/* return 0; */ +/* } */ /* /\* Wait for condition variable COND to be signaled or broadcast until */ /* ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an */ diff --git a/src/AdjList.hpp b/src/ADT/AdjList.hpp similarity index 98% rename from src/AdjList.hpp rename to src/ADT/AdjList.hpp index 7825d63..7778663 100644 --- a/src/AdjList.hpp +++ b/src/ADT/AdjList.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ADJ_LIST_HPP__ -#define __ADJ_LIST_HPP__ +#ifndef GENMC_ADJ_LIST_HPP +#define GENMC_ADJ_LIST_HPP #include #include @@ -197,4 +197,4 @@ template > class AdjList { #include "AdjList.tcc" -#endif /* __ADJ_LIST_HPP__ */ +#endif /* GENMC_ADJ_LIST_HPP */ diff --git a/src/AdjList.tcc b/src/ADT/AdjList.tcc similarity index 99% rename from src/AdjList.tcc rename to src/ADT/AdjList.tcc index 6dbf3c1..5f19311 100644 --- a/src/AdjList.tcc +++ b/src/ADT/AdjList.tcc @@ -18,7 +18,7 @@ * Author: Michalis Kokologiannakis */ -#include "Error.hpp" +#include "Support/Error.hpp" template void AdjList::addNode(T a) diff --git a/src/Bitmask.hpp b/src/ADT/Bitmask.hpp similarity index 97% rename from src/Bitmask.hpp rename to src/ADT/Bitmask.hpp index 270e911..a100b6a 100644 --- a/src/Bitmask.hpp +++ b/src/ADT/Bitmask.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __BITMASK_HPP__ -#define __BITMASK_HPP__ +#ifndef GENMC_BITMASK_HPP +#define GENMC_BITMASK_HPP #include @@ -76,4 +76,4 @@ DEFINE_ASSIGNMENT_OPERATOR(|); DEFINE_ASSIGNMENT_OPERATOR(&); DEFINE_ASSIGNMENT_OPERATOR(^); -#endif /* __BITMASK_HPP__ */ +#endif /* GENMC_BITMASK_HPP */ diff --git a/src/DepView.cpp b/src/ADT/DepView.cpp similarity index 97% rename from src/DepView.cpp rename to src/ADT/DepView.cpp index 2b5229b..0af50c5 100644 --- a/src/DepView.cpp +++ b/src/ADT/DepView.cpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#include "DepView.hpp" -#include "Error.hpp" +#include "ADT/DepView.hpp" +#include "Support/Error.hpp" bool DepView::contains(const Event e) const { diff --git a/src/DepView.hpp b/src/ADT/DepView.hpp similarity index 95% rename from src/DepView.hpp rename to src/ADT/DepView.hpp index a740936..8b81cc2 100644 --- a/src/DepView.hpp +++ b/src/ADT/DepView.hpp @@ -18,13 +18,13 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DEP_VIEW_HPP__ -#define __DEP_VIEW_HPP__ +#ifndef GENMC_DEP_VIEW_HPP +#define GENMC_DEP_VIEW_HPP -#include "Error.hpp" -#include "VSet.hpp" -#include "VectorClock.hpp" -#include "View.hpp" +#include "ADT/VSet.hpp" +#include "ADT/VectorClock.hpp" +#include "ADT/View.hpp" +#include "Support/Error.hpp" #include #include @@ -150,4 +150,4 @@ class DepView : public VectorClock { HoleView holes_; }; -#endif /* __DEP_VIEW_HPP__ */ +#endif /* GENMC_DEP_VIEW_HPP */ diff --git a/src/Matrix2D.hpp b/src/ADT/Matrix2D.hpp similarity index 98% rename from src/Matrix2D.hpp rename to src/ADT/Matrix2D.hpp index 2576955..5aa9bc9 100644 --- a/src/Matrix2D.hpp +++ b/src/ADT/Matrix2D.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MATRIX_2D_HPP__ -#define __MATRIX_2D_HPP__ +#ifndef GENMC_MATRIX_2D_HPP +#define GENMC_MATRIX_2D_HPP #include @@ -172,4 +172,4 @@ template class Matrix2D { #include "Matrix2D.tcc" -#endif /* __MATRIX_2D_HPP__ */ +#endif /* GENMC_MATRIX_2D_HPP */ diff --git a/src/Matrix2D.tcc b/src/ADT/Matrix2D.tcc similarity index 100% rename from src/Matrix2D.tcc rename to src/ADT/Matrix2D.tcc diff --git a/src/Trie.hpp b/src/ADT/Trie.hpp similarity index 99% rename from src/Trie.hpp rename to src/ADT/Trie.hpp index 349b530..82ee039 100644 --- a/src/Trie.hpp +++ b/src/ADT/Trie.hpp @@ -21,7 +21,7 @@ #ifndef GENMC_TRIE_HPP #define GENMC_TRIE_HPP -#include "Error.hpp" +#include "Support/Error.hpp" #include #include diff --git a/src/VSet.hpp b/src/ADT/VSet.hpp similarity index 97% rename from src/VSet.hpp rename to src/ADT/VSet.hpp index e1fce52..67195e2 100644 --- a/src/VSet.hpp +++ b/src/ADT/VSet.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VSET_HPP__ -#define __VSET_HPP__ +#ifndef GENMC_VSET_HPP +#define GENMC_VSET_HPP #include #include @@ -98,4 +98,4 @@ template class VSet { #include "VSet.tcc" -#endif /* __VSET_HPP__ */ +#endif /* GENMC_VSET_HPP */ diff --git a/src/VSet.tcc b/src/ADT/VSet.tcc similarity index 100% rename from src/VSet.tcc rename to src/ADT/VSet.tcc diff --git a/src/VectorClock.cpp b/src/ADT/VectorClock.cpp similarity index 93% rename from src/VectorClock.cpp rename to src/ADT/VectorClock.cpp index 7517360..8619f01 100644 --- a/src/VectorClock.cpp +++ b/src/ADT/VectorClock.cpp @@ -19,9 +19,9 @@ */ #include "VectorClock.hpp" -#include "DepView.hpp" -#include "EventLabel.hpp" -#include "View.hpp" +#include "ADT/DepView.hpp" +#include "ADT/View.hpp" +#include "ExecutionGraph/EventLabel.hpp" bool VectorClock::contains(const EventLabel *lab) const { return contains(lab->getPos()); } diff --git a/src/VectorClock.hpp b/src/ADT/VectorClock.hpp similarity index 95% rename from src/VectorClock.hpp rename to src/ADT/VectorClock.hpp index 5585e18..cb2ce4b 100644 --- a/src/VectorClock.hpp +++ b/src/ADT/VectorClock.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VECTOR_CLOCK_HPP__ -#define __VECTOR_CLOCK_HPP__ +#ifndef GENMC_VECTOR_CLOCK_HPP +#define GENMC_VECTOR_CLOCK_HPP -#include "Event.hpp" +#include "ExecutionGraph/Event.hpp" #include /******************************************************************************* @@ -100,4 +100,4 @@ struct VectorClockCloner { // VectorClock *operator()(VectorClock &&x) const { return new VectorClock(std::move(x)); } }; -#endif /* __VECTOR_CLOCK_HPP__ */ +#endif /* GENMC_VECTOR_CLOCK_HPP */ diff --git a/src/View.cpp b/src/ADT/View.cpp similarity index 96% rename from src/View.cpp rename to src/ADT/View.cpp index 33ee9ac..3f99f92 100644 --- a/src/View.cpp +++ b/src/ADT/View.cpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#include "View.hpp" -#include "Error.hpp" +#include "ADT/View.hpp" +#include "Support/Error.hpp" View &View::update(const View &v) { diff --git a/src/View.hpp b/src/ADT/View.hpp similarity index 94% rename from src/View.hpp rename to src/ADT/View.hpp index df30120..63bb650 100644 --- a/src/View.hpp +++ b/src/ADT/View.hpp @@ -18,12 +18,12 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VIEW_HPP__ -#define __VIEW_HPP__ +#ifndef GENMC_VIEW_HPP +#define GENMC_VIEW_HPP -#include "Error.hpp" -#include "Event.hpp" -#include "VectorClock.hpp" +#include "ADT/VectorClock.hpp" +#include "ExecutionGraph/Event.hpp" +#include "Support/Error.hpp" #include #include @@ -101,4 +101,4 @@ class View : public VectorClock { static bool classof(const VectorClock *vc) { return vc->getKind() == VC_View; } }; -#endif /* __VIEW_HPP__ */ +#endif /* GENMC_VIEW_HPP */ diff --git a/src/value_ptr.hpp b/src/ADT/value_ptr.hpp similarity index 98% rename from src/value_ptr.hpp rename to src/ADT/value_ptr.hpp index f531854..6deb8ce 100644 --- a/src/value_ptr.hpp +++ b/src/ADT/value_ptr.hpp @@ -44,8 +44,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VALUE_PTR_HPP__ -#define __VALUE_PTR_HPP__ +#ifndef GENMC_VALUE_PTR_HPP +#define GENMC_VALUE_PTR_HPP #include #ifdef _MSC_VER @@ -197,4 +197,4 @@ class value_ptr { #undef DECLSPEC_EMPTY_BASES -#endif /* __VALUE_PTR_HPP__ */ +#endif /* GENMC_VALUE_PTR_HPP */ diff --git a/src/CallInfoCollectionPass.hpp b/src/CallInfoCollectionPass.hpp deleted file mode 100644 index 7fc0863..0000000 --- a/src/CallInfoCollectionPass.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __CALL_INFO_COLLECTION_PASS_HPP__ -#define __CALL_INFO_COLLECTION_PASS_HPP__ - -#include "VSet.hpp" -#include -#include - -#include -#include -#include - -class CallInfoCollectionPass : public llvm::ModulePass { - -public: - using CallSet = VSet; - - CallInfoCollectionPass() : llvm::ModulePass(ID) {} - - /* Returns the set of side-effect-free calls */ - const CallSet &getCleanCalls() const { return clean; } - - /* Returns the set of (non-builtin) allocating calls */ - const CallSet &getAllocCalls() const { return alloc; } - - virtual bool runOnModule(llvm::Module &M); - void getAnalysisUsage(llvm::AnalysisUsage &au) const; - - static char ID; - -private: - CallSet clean; - CallSet alloc; -}; - -#endif /* __CALL_INFO_COLLECTION_PASS_HPP__ */ diff --git a/src/CallInstWrapper.hpp b/src/CallInstWrapper.hpp deleted file mode 100644 index 714e59d..0000000 --- a/src/CallInstWrapper.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __CALL_INST_WRAPPER_HPP__ -#define __CALL_INST_WRAPPER_HPP__ - -#include "config.h" -#include - -#if LLVM_VERSION_MAJOR < 11 -#include -#endif - -using namespace llvm; - -/* - * The class llvm::CallSite was removed in LLVM 11 in favor of - * llvm::CallBase. To maintain compatibility with older versions that - * still utilize this class CallInstWrapper can be used instead; it - * boils down to either llvm::CallSite or llvm::CallBase. - */ - -#if LLVM_VERSION_MAJOR < 11 -class CallInstWrapper { - -public: - /* Constructors */ - CallInstWrapper() : CS() {} - CallInstWrapper(CallSite CS) : CS(CS) {} - CallInstWrapper(CallInst *CI) : CS(CI) {} - - /* Getters emulation */ - llvm::Value *getCalledOperand() { return CS.getCalledValue(); } - llvm::Function *getCalledFunction() { return CS.getCalledFunction(); } - size_t arg_size() const { return CS.arg_size(); } - CallSite::arg_iterator arg_begin() { return CS.arg_begin(); } - CallSite::arg_iterator arg_end() { return CS.arg_end(); } - - /* Operators to use instead of member functions like - * getInstruction() that do not exist in CallBase */ - Instruction *operator&() { return CS.getInstruction(); } - -private: - CallSite CS; -}; - -#else - -class CallInstWrapper { - -public: - /* Constructors */ - CallInstWrapper() : CB(nullptr) {} - CallInstWrapper(CallBase *CB) : CB(CB) {} - CallInstWrapper(CallBase &CB) : CB(&CB) {} - CallInstWrapper(CallInst *CI) : CB(CI) {} - - /* Getters emulation */ - llvm::Value *getCalledOperand() { return CB->getCalledOperand(); } - llvm::Function *getCalledFunction() { return CB->getCalledFunction(); } - size_t arg_size() const { return CB->arg_size(); } - User::op_iterator arg_begin() { return CB->arg_begin(); } - User::op_iterator arg_end() { return CB->arg_end(); } - - Instruction *operator&() { return CB; } - -private: - CallBase *CB; -}; -#endif - -#endif /* __CALL_INST_WRAPPER__ */ diff --git a/src/Config.cpp b/src/Config/Config.cpp similarity index 98% rename from src/Config.cpp rename to src/Config/Config.cpp index 9f7214c..95769a7 100644 --- a/src/Config.cpp +++ b/src/Config/Config.cpp @@ -19,9 +19,9 @@ */ #include "config.h" -#include "Config.hpp" -#include "Error.hpp" -#include "Logger.hpp" +#include "Config/Config.hpp" +#include "Support/Error.hpp" +#include "Support/Logger.hpp" #include #include #include @@ -113,6 +113,9 @@ static llvm::cl::opt clDisableIPR("disable-ipr", llvm::cl::cat(clGeneral), static llvm::cl::opt clDisableStopOnSystemError("disable-stop-on-system-error", llvm::cl::cat(clGeneral), llvm::cl::desc("Do not stop verification on system errors")); +static llvm::cl::opt + clDisableWarnUnfreedMemory("disable-warn-on-unfreed-memory", llvm::cl::cat(clGeneral), + llvm::cl::desc("Do not warn about unfreed memory")); /*** Persistency options ***/ @@ -367,6 +370,7 @@ void Config::saveConfigOptions() disableBAM = clDisableBAM; ipr = !clDisableIPR; disableStopOnSystemError = clDisableStopOnSystemError; + warnUnfreedMemory = !clDisableWarnUnfreedMemory; /* Save persistency options */ persevere = clPersevere; diff --git a/src/Config.hpp b/src/Config/Config.hpp similarity index 91% rename from src/Config.hpp rename to src/Config/Config.hpp index a4f42bf..a20c081 100644 --- a/src/Config.hpp +++ b/src/Config/Config.hpp @@ -18,13 +18,13 @@ * Author: Michalis Kokologiannakis */ -#ifndef __CONFIG_HPP__ -#define __CONFIG_HPP__ +#ifndef GENMC_CONFIG_HPP +#define GENMC_CONFIG_HPP -#include "InterpreterEnumAPI.hpp" -#include "MemoryModel.hpp" -#include "VSet.hpp" -#include "Verbosity.hpp" +#include "ADT/VSet.hpp" +#include "Config/MemoryModel.hpp" +#include "Config/Verbosity.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" #include #include @@ -57,6 +57,7 @@ struct Config { bool disableBAM; bool ipr; bool disableStopOnSystemError; + bool warnUnfreedMemory; /*** Persistency options ***/ bool persevere; @@ -110,4 +111,4 @@ struct Config { void saveConfigOptions(); }; -#endif /* __CONFIG_HPP__ */ +#endif /* GENMC_CONFIG_HPP */ diff --git a/src/MemoryModel.hpp b/src/Config/MemoryModel.hpp similarity index 92% rename from src/MemoryModel.hpp rename to src/Config/MemoryModel.hpp index 9d524b1..2812c2b 100644 --- a/src/MemoryModel.hpp +++ b/src/Config/MemoryModel.hpp @@ -18,10 +18,11 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MEMORY_MODEL_HPP__ -#define __MEMORY_MODEL_HPP__ +#ifndef GENMC_MEMORY_MODEL_HPP +#define GENMC_MEMORY_MODEL_HPP -#include "Error.hpp" +#include "Support/Error.hpp" +#include "config.h" #include #include @@ -60,4 +61,4 @@ inline auto isStrongerThan(ModelType model, ModelType other) -> bool return lookup[static_cast(model)][static_cast(other)]; } -#endif /* __MEMORY_MODEL_HPP__ */ +#endif /* GENMC_MEMORY_MODEL_HPP */ diff --git a/src/Verbosity.cpp b/src/Config/Verbosity.cpp similarity index 100% rename from src/Verbosity.cpp rename to src/Config/Verbosity.cpp diff --git a/src/Verbosity.hpp b/src/Config/Verbosity.hpp similarity index 92% rename from src/Verbosity.hpp rename to src/Config/Verbosity.hpp index b94dd97..c6163bf 100644 --- a/src/Verbosity.hpp +++ b/src/Config/Verbosity.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VERBOSITY_HPP__ -#define __VERBOSITY_HPP__ +#ifndef GENMC_VERBOSITY_HPP +#define GENMC_VERBOSITY_HPP #include @@ -38,4 +38,4 @@ enum class VerbosityLevel { auto operator<<(llvm::raw_ostream &rhs, VerbosityLevel l) -> llvm::raw_ostream &; -#endif /* __VERBOSITY_HPP__ */ +#endif /* GENMC_VERBOSITY_HPP */ diff --git a/src/DefineLibcFunsPass.hpp b/src/DefineLibcFunsPass.hpp deleted file mode 100644 index a41a6b3..0000000 --- a/src/DefineLibcFunsPass.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __DEFINE_LIBC_FUNS_PASS_HPP__ -#define __DEFINE_LIBC_FUNS_PASS_HPP__ - -#include - -class DefineLibcFunsPass : public llvm::ModulePass { - -public: - static char ID; - - DefineLibcFunsPass() : ModulePass(ID){}; - virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const; - virtual bool runOnModule(llvm::Module &M); - -protected: - virtual void replaceFunWithNop(llvm::Module &M, std::string name); -}; - -#endif /* __DEFINE_LIBC_FUNS_PASS_HPP__ */ diff --git a/src/EliminateAnnotationsPass.hpp b/src/EliminateAnnotationsPass.hpp deleted file mode 100644 index 0d7d451..0000000 --- a/src/EliminateAnnotationsPass.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __ELIMINATE_ANNOTATIONS_PASS_HPP__ -#define __ELIMINATE_ANNOTATIONS_PASS_HPP__ - -#include - -class EliminateAnnotationsPass : public llvm::FunctionPass { - -public: - static char ID; - - EliminateAnnotationsPass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; -}; - -#endif /* __ELIMINATE_ANNOTATIONS_PASS_HPP__ */ diff --git a/src/EliminateRedundantInstPass.hpp b/src/EliminateRedundantInstPass.hpp deleted file mode 100644 index a962809..0000000 --- a/src/EliminateRedundantInstPass.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __ELIMINATE_REDUNDANT_INST_PASS_HPP__ -#define __ELIMINATE_REDUNDANT_INST_PASS_HPP__ - -#include - -class EliminateRedundantInstPass : public llvm::FunctionPass { - -public: - static char ID; - - EliminateRedundantInstPass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; -}; - -#endif /* __ELIMINATE_REDUNDANT_INST_PASS_HPP__ */ diff --git a/src/EliminateUnusedCodePass.hpp b/src/EliminateUnusedCodePass.hpp deleted file mode 100644 index 7eae235..0000000 --- a/src/EliminateUnusedCodePass.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __ELIMINATE_UNUSED_CODE_PASS_HPP__ -#define __ELIMINATE_UNUSED_CODE_PASS_HPP__ - -#include - -class EliminateUnusedCodePass : public llvm::FunctionPass { - -public: - static char ID; - - EliminateUnusedCodePass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; -}; - -#endif /* __ELIMINATE_UNUSED_CODE_PASS_HPP__ */ diff --git a/src/EventLabel.cpp b/src/EventLabel.cpp deleted file mode 100644 index e651a4b..0000000 --- a/src/EventLabel.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#include "EventLabel.hpp" -#include "LabelVisitor.hpp" - -llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const EventLabel::EventLabelKind k) -{ - switch (k) { - case EventLabel::EL_Empty: - s << "EMPTY"; - break; - case EventLabel::EL_JoinBlock: - s << "BLOCK[join]"; - break; - case EventLabel::EL_SpinloopBlock: - s << "BLOCK[spinloop]"; - break; - case EventLabel::EL_FaiZNEBlock: - s << "BLOCK[Fai-zne]"; - break; - case EventLabel::EL_LockZNEBlock: - s << "BLOCK[Lock-zne]"; - break; - case EventLabel::EL_HelpedCASBlock: - s << "BLOCK[helped-cas]"; - break; - case EventLabel::EL_ConfirmationBlock: - s << "BLOCK[conf]"; - break; - case EventLabel::EL_LockNotAcqBlock: - s << "BLOCK[lock-unacq]"; - break; - case EventLabel::EL_LockNotRelBlock: - s << "BLOCK[lock-unrel]"; - break; - case EventLabel::EL_BarrierBlock: - s << "BLOCK[barrier]"; - break; - case EventLabel::EL_ErrorBlock: - s << "BLOCK[error]"; - break; - case EventLabel::EL_UserBlock: - s << "BLOCK[user]"; - break; - case EventLabel::EL_ReadOptBlock: - s << "BLOCK[read-opt]"; - break; - case EventLabel::EL_ThreadKill: - s << "KILL"; - break; - case EventLabel::EL_Optional: - s << "OPTIONAL"; - break; - case EventLabel::EL_LoopBegin: - s << "LOOP_BEGIN"; - break; - case EventLabel::EL_SpinStart: - s << "SPIN_START"; - break; - case EventLabel::EL_FaiZNESpinEnd: - case EventLabel::EL_LockZNESpinEnd: - s << "ZNE_SPIN_END"; - break; - case EventLabel::EL_Read: - case EventLabel::EL_BWaitRead: - case EventLabel::EL_SpeculativeRead: - case EventLabel::EL_ConfirmingRead: - s << "R"; - break; - case EventLabel::EL_FaiRead: - case EventLabel::EL_BIncFaiRead: - case EventLabel::EL_NoRetFaiRead: - s << "UR"; - break; - case EventLabel::EL_FaiWrite: - case EventLabel::EL_BIncFaiWrite: - case EventLabel::EL_NoRetFaiWrite: - s << "UW"; - break; - case EventLabel::EL_CasRead: - case EventLabel::EL_LockCasRead: - case EventLabel::EL_TrylockCasRead: - case EventLabel::EL_HelpedCasRead: - case EventLabel::EL_ConfirmingCasRead: - s << "CR"; - break; - case EventLabel::EL_CasWrite: - case EventLabel::EL_LockCasWrite: - case EventLabel::EL_TrylockCasWrite: - case EventLabel::EL_HelpedCasWrite: - case EventLabel::EL_ConfirmingCasWrite: - s << "CW"; - break; - case EventLabel::EL_HelpingCas: - s << "HELPING_CAS"; - break; - case EventLabel::EL_Write: - case EventLabel::EL_BInitWrite: - case EventLabel::EL_BDestroyWrite: - case EventLabel::EL_UnlockWrite: - s << "W"; - break; - case EventLabel::EL_Fence: - case EventLabel::EL_SmpFenceLKMM: - s << "F"; - break; - case EventLabel::EL_CLFlush: - s << "CLF"; - break; - case EventLabel::EL_ThreadCreate: - s << "THREAD_CREATE"; - break; - case EventLabel::EL_ThreadJoin: - s << "THREAD_JOIN"; - break; - case EventLabel::EL_ThreadStart: - s << "THREAD_START"; - break; - case EventLabel::EL_Init: - s << "INIT"; - break; - case EventLabel::EL_ThreadFinish: - s << "THREAD_END"; - break; - case EventLabel::EL_Malloc: - s << "MALLOC"; - break; - case EventLabel::EL_Free: - s << "FREE"; - break; - case EventLabel::EL_HpRetire: - s << "HP_RETIRE"; - break; - case EventLabel::EL_HpProtect: - s << "HP_PROTECT"; - break; - case EventLabel::EL_LockLAPOR: - s << "LAPOR_LOCK"; - break; - case EventLabel::EL_UnlockLAPOR: - s << "LAPOR_UNLOCK"; - break; - case EventLabel::EL_DskOpen: - s << "FOPEN"; - break; - case EventLabel::EL_DskRead: - s << "DR"; - break; - case EventLabel::EL_DskWrite: - case EventLabel::EL_DskMdWrite: - case EventLabel::EL_DskDirWrite: - case EventLabel::EL_DskJnlWrite: - s << "DW"; - break; - case EventLabel::EL_DskFsync: - s << "FSYNC"; - break; - case EventLabel::EL_DskSync: - s << "SYNC"; - break; - case EventLabel::EL_DskPbarrier: - s << "PERSISTENCY_BARRIER"; - break; - case EventLabel::EL_RCULockLKMM: - s << "RCU_LOCK"; - break; - case EventLabel::EL_RCUUnlockLKMM: - s << "RCU_UNLOCK"; - break; - case EventLabel::EL_RCUSyncLKMM: - s << "RCU_SYNC"; - break; - default: - PRINT_BUGREPORT_INFO_ONCE("print-label-type", "Cannot print label type"); - s << "UNKNOWN"; - break; - } - return s; -} - -llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const llvm::AtomicOrdering o) -{ - switch (o) { - case llvm::AtomicOrdering::NotAtomic: - return s << "na"; - case llvm::AtomicOrdering::Unordered: - return s << "un"; - case llvm::AtomicOrdering::Monotonic: - return s << "rlx"; - case llvm::AtomicOrdering::Acquire: - return s << "acq"; - case llvm::AtomicOrdering::Release: - return s << "rel"; - case llvm::AtomicOrdering::AcquireRelease: - return s << "ar"; - case llvm::AtomicOrdering::SequentiallyConsistent: - return s << "sc"; - default: - PRINT_BUGREPORT_INFO_ONCE("print-ordering-type", "Cannot print ordering"); - return s; - } - return s; -} - -llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const SmpFenceType t) -{ - switch (t) { - case SmpFenceType::MB: - return s << "mb"; - case SmpFenceType::WMB: - return s << "wmb"; - case SmpFenceType::RMB: - return s << "rmb"; - case SmpFenceType::MBBA: - return s << "ba"; - case SmpFenceType::MBAA: - return s << "aa"; - case SmpFenceType::MBAS: - return s << "as"; - case SmpFenceType::MBAUL: - return s << "aul"; - default: - PRINT_BUGREPORT_INFO_ONCE("print-fence-type", "Cannot print fence type"); - } - return s; -} - -llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const EventLabel &lab) -{ - s << LabelPrinter().toString(lab); - return s; -} diff --git a/src/DepExecutionGraph.cpp b/src/ExecutionGraph/DepExecutionGraph.cpp similarity index 94% rename from src/DepExecutionGraph.cpp rename to src/ExecutionGraph/DepExecutionGraph.cpp index b44b1f9..9f4f66c 100644 --- a/src/DepExecutionGraph.cpp +++ b/src/ExecutionGraph/DepExecutionGraph.cpp @@ -72,6 +72,9 @@ void DepExecutionGraph::cutToStamp(Stamp stamp) /* Inform all calculators about the events cutted */ removeAfter(*preds); + for (auto labIt = insertionOrder.begin(); labIt != insertionOrder.end();) { + labIt = preds->contains(labIt->getPos()) ? ++labIt : insertionOrder.erase(labIt); + } /* Then, restrict the graph */ for (auto i = 0u; i < preds->size(); i++) { @@ -127,6 +130,8 @@ void DepExecutionGraph::cutToStamp(Stamp stamp) continue; setEventLabel(Event(i, j), createHoleLabel(Event(i, j))); getEventLabel(Event(i, j))->setStamp(nextStamp()); + getEventLabel(Event(i, j))->setParent(this); + insertionOrder.push_back(*getEventLabel(Event(i, j))); } } } diff --git a/src/DepExecutionGraph.hpp b/src/ExecutionGraph/DepExecutionGraph.hpp similarity index 93% rename from src/DepExecutionGraph.hpp rename to src/ExecutionGraph/DepExecutionGraph.hpp index c056632..c7c1412 100644 --- a/src/DepExecutionGraph.hpp +++ b/src/ExecutionGraph/DepExecutionGraph.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DEP_EXECUTION_GRAPH_HPP__ -#define __DEP_EXECUTION_GRAPH_HPP__ +#ifndef GENMC_DEP_EXECUTION_GRAPH_HPP +#define GENMC_DEP_EXECUTION_GRAPH_HPP #include "ExecutionGraph.hpp" @@ -50,4 +50,4 @@ class DepExecutionGraph : public ExecutionGraph { std::unique_ptr getCopyUpTo(const VectorClock &v) const override; }; -#endif /* __DEP_EXECUTION_GRAPH_HPP__ */ +#endif /* GENMC_DEP_EXECUTION_GRAPH_HPP */ diff --git a/src/DepInfo.cpp b/src/ExecutionGraph/DepInfo.cpp similarity index 100% rename from src/DepInfo.cpp rename to src/ExecutionGraph/DepInfo.cpp diff --git a/src/DepInfo.hpp b/src/ExecutionGraph/DepInfo.hpp similarity index 96% rename from src/DepInfo.hpp rename to src/ExecutionGraph/DepInfo.hpp index 2822e96..617100c 100644 --- a/src/DepInfo.hpp +++ b/src/ExecutionGraph/DepInfo.hpp @@ -18,11 +18,11 @@ n * You should have received a copy of the GNU General Public License * Author: Michalis Kokologiannakis */ -#ifndef __DEP_INFO_HPP__ -#define __DEP_INFO_HPP__ +#ifndef GENMC_DEP_INFO_HPP +#define GENMC_DEP_INFO_HPP +#include "ADT/VSet.hpp" #include "Event.hpp" -#include "VSet.hpp" #include /******************************************************************************* @@ -92,4 +92,4 @@ struct EventDeps { DepInfo cas; }; -#endif /* __DEP_INFO_HPP__ */ +#endif /* GENMC_DEP_INFO_HPP */ diff --git a/src/Event.cpp b/src/ExecutionGraph/Event.cpp similarity index 100% rename from src/Event.cpp rename to src/ExecutionGraph/Event.cpp diff --git a/src/Event.hpp b/src/ExecutionGraph/Event.hpp similarity index 90% rename from src/Event.hpp rename to src/ExecutionGraph/Event.hpp index dd27917..047898f 100644 --- a/src/Event.hpp +++ b/src/ExecutionGraph/Event.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __EVENT_HPP__ -#define __EVENT_HPP__ +#ifndef GENMC_EVENT_HPP +#define GENMC_EVENT_HPP #include #include @@ -53,8 +53,8 @@ struct Event { /** Returns the po-successor. No bounds checking is performed */ [[nodiscard]] auto next() const -> Event { return {thread, index + 1}; }; - inline auto operator==(const Event &) const -> bool = default; - inline auto operator<=>(const Event &other) const -> std::partial_ordering + [[nodiscard]] inline auto operator==(const Event &) const -> bool = default; + [[nodiscard]] inline auto operator<=>(const Event &other) const -> std::partial_ordering { return this->thread == other.thread ? this->index <=> other.index : std::partial_ordering::unordered; @@ -83,7 +83,7 @@ struct Event { return tmp; } - friend auto hash_value(const Event &e) -> llvm::hash_code + static auto hash_value(const Event &e) -> llvm::hash_code { return llvm::hash_combine(e.thread, e.index); }; @@ -116,4 +116,4 @@ struct EventHasher { } }; -#endif /* __EVENT_HPP__ */ +#endif /* GENMC_EVENT_HPP */ diff --git a/src/EventAttr.hpp b/src/ExecutionGraph/EventAttr.hpp similarity index 89% rename from src/EventAttr.hpp rename to src/ExecutionGraph/EventAttr.hpp index 3ad02fb..e9b3e63 100644 --- a/src/EventAttr.hpp +++ b/src/ExecutionGraph/EventAttr.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __EVENT_ATTR_HPP__ -#define __EVENT_ATTR_HPP__ +#ifndef GENMC_EVENT_ATTR_HPP +#define GENMC_EVENT_ATTR_HPP -#include "Bitmask.hpp" +#include "ADT/Bitmask.hpp" /* * Attributes for write events @@ -36,4 +36,4 @@ enum class WriteAttr { ENABLE_BITMASK_OPERATORS(WriteAttr); -#endif /* __EVENT_ATTR_HPP__ */ +#endif /* GENMC_EVENT_ATTR_HPP */ diff --git a/src/ExecutionGraph/EventLabel.cpp b/src/ExecutionGraph/EventLabel.cpp new file mode 100644 index 0000000..5f44026 --- /dev/null +++ b/src/ExecutionGraph/EventLabel.cpp @@ -0,0 +1,192 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#include "EventLabel.hpp" +#include "LabelVisitor.hpp" + +llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const EventLabel::EventLabelKind k) +{ + switch (k) { + case EventLabel::ThreadStart: + s << "THREAD_START"; + break; + case EventLabel::Init: + s << "INIT"; + break; + case EventLabel::JoinBlock: + s << "BLOCK[join]"; + break; + case EventLabel::SpinloopBlock: + s << "BLOCK[spinloop]"; + break; + case EventLabel::FaiZNEBlock: + s << "BLOCK[Fai-zne]"; + break; + case EventLabel::LockZNEBlock: + s << "BLOCK[Lock-zne]"; + break; + case EventLabel::HelpedCASBlock: + s << "BLOCK[helped-cas]"; + break; + case EventLabel::ConfirmationBlock: + s << "BLOCK[conf]"; + break; + case EventLabel::LockNotAcqBlock: + s << "BLOCK[lock-unacq]"; + break; + case EventLabel::LockNotRelBlock: + s << "BLOCK[lock-unrel]"; + break; + case EventLabel::BarrierBlock: + s << "BLOCK[barrier]"; + break; + case EventLabel::ErrorBlock: + s << "BLOCK[error]"; + break; + case EventLabel::UserBlock: + s << "BLOCK[user]"; + break; + case EventLabel::ReadOptBlock: + s << "BLOCK[read-opt]"; + break; + case EventLabel::ThreadKill: + s << "KILL"; + break; + case EventLabel::ThreadFinish: + s << "THREAD_END"; + break; + case EventLabel::Read: + case EventLabel::BWaitRead: + case EventLabel::CondVarWaitRead: + case EventLabel::SpeculativeRead: + case EventLabel::ConfirmingRead: + s << "R"; + break; + case EventLabel::CasRead: + case EventLabel::LockCasRead: + case EventLabel::TrylockCasRead: + case EventLabel::HelpedCasRead: + case EventLabel::ConfirmingCasRead: + s << "CR"; + break; + case EventLabel::FaiRead: + case EventLabel::BIncFaiRead: + case EventLabel::NoRetFaiRead: + s << "UR"; + break; + case EventLabel::Write: + case EventLabel::BInitWrite: + case EventLabel::BDestroyWrite: + case EventLabel::CondVarInitWrite: + case EventLabel::CondVarSignalWrite: + case EventLabel::CondVarBcastWrite: + case EventLabel::CondVarDestroyWrite: + case EventLabel::UnlockWrite: + s << "W"; + break; + case EventLabel::CasWrite: + case EventLabel::LockCasWrite: + case EventLabel::TrylockCasWrite: + case EventLabel::HelpedCasWrite: + case EventLabel::ConfirmingCasWrite: + s << "CW"; + break; + case EventLabel::FaiWrite: + case EventLabel::BIncFaiWrite: + case EventLabel::NoRetFaiWrite: + s << "UW"; + break; + case EventLabel::Fence: + s << "F"; + break; + case EventLabel::Malloc: + s << "MALLOC"; + break; + case EventLabel::Free: + s << "FREE"; + break; + case EventLabel::HpRetire: + s << "HP_RETIRE"; + break; + case EventLabel::ThreadCreate: + s << "THREAD_CREATE"; + break; + case EventLabel::ThreadJoin: + s << "THREAD_JOIN"; + break; + case EventLabel::HelpingCas: + s << "HELPING_CAS"; + break; + case EventLabel::HpProtect: + s << "HP_PROTECT"; + case EventLabel::Optional: + s << "OPTIONAL"; + break; + case EventLabel::LoopBegin: + s << "LOOP_BEGIN"; + break; + case EventLabel::SpinStart: + s << "SPIN_START"; + break; + case EventLabel::FaiZNESpinEnd: + case EventLabel::LockZNESpinEnd: + s << "ZNE_SPIN_END"; + break; + break; + case EventLabel::Empty: + s << "EMPTY"; + break; + default: + PRINT_BUGREPORT_INFO_ONCE("print-label-type", "Cannot print label type"); + s << "UNKNOWN"; + break; + } + return s; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const llvm::AtomicOrdering o) +{ + switch (o) { + case llvm::AtomicOrdering::NotAtomic: + return s << "na"; + case llvm::AtomicOrdering::Unordered: + return s << "un"; + case llvm::AtomicOrdering::Monotonic: + return s << "rlx"; + case llvm::AtomicOrdering::Acquire: + return s << "acq"; + case llvm::AtomicOrdering::Release: + return s << "rel"; + case llvm::AtomicOrdering::AcquireRelease: + return s << "ar"; + case llvm::AtomicOrdering::SequentiallyConsistent: + return s << "sc"; + default: + PRINT_BUGREPORT_INFO_ONCE("print-ordering-type", "Cannot print ordering"); + return s; + } + return s; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const EventLabel &lab) +{ + s << LabelPrinter().toString(lab); + return s; +} diff --git a/src/ExecutionGraph/EventLabel.def b/src/ExecutionGraph/EventLabel.def new file mode 100644 index 0000000..7e30394 --- /dev/null +++ b/src/ExecutionGraph/EventLabel.def @@ -0,0 +1,410 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/*** NOTE: No include guard ***/ + +#ifndef FIRST_BEGIN_LABEL +#define FIRST_BEGIN_LABEL(num) +#endif +#ifndef HANDLE_BEGIN_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_BEGIN_LABEL(num, name) +#else +#define HANDLE_BEGIN_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_BEGIN_LABEL +#define LAST_BEGIN_LABEL(num) +#endif + +#ifndef FIRST_TERM_LABEL +#define FIRST_TERM_LABEL(num) +#endif +#ifndef HANDLE_TERM_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_TERM_LABEL(num, name) +#else +#define HANDLE_TERM_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_TERM_LABEL +#define LAST_TERM_LABEL(num) +#endif + +#ifndef FIRST_BLOCK_LABEL +#define FIRST_BLOCK_LABEL(num) +#endif +#ifndef HANDLE_BLOCK_LABEL +#ifndef HANDLE_TERM_LABEL +#define HANDLE_BLOCK_LABEL(num, name) +#else +#define HANDLE_BLOCK_LABEL(num, name) HANDLE_TERM_LABEL(num, name) +#endif +#endif +#ifndef LAST_BLOCK_LABEL +#define LAST_BLOCK_LABEL(num) +#endif + +#ifndef FIRST_MEMORY_LABEL +#define FIRST_MEMORY_LABEL(num) +#endif +#ifndef HANDLE_MEMORY_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_MEMORY_LABEL(num, name) +#else +#define HANDLE_MEMORY_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_MEMORY_LABEL +#define LAST_MEMORY_LABEL(num) +#endif + +#ifndef FIRST_READ_LABEL +#define FIRST_READ_LABEL(num) +#endif +#ifndef HANDLE_READ_LABEL +#ifndef HANDLE_MEMORY_LABEL +#define HANDLE_READ_LABEL(num, name) +#else +#define HANDLE_READ_LABEL(num, name) HANDLE_MEMORY_LABEL(num, name) +#endif +#endif +#ifndef LAST_READ_LABEL +#define LAST_READ_LABEL(num) +#endif + +#ifndef FIRST_CAS_READ_LABEL +#define FIRST_CAS_READ_LABEL(num) +#endif +#ifndef HANDLE_CAS_READ_LABEL +#ifndef HANDLE_READ_LABEL +#define HANDLE_CAS_READ_LABEL(num, name) +#else +#define HANDLE_CAS_READ_LABEL(num, name) HANDLE_READ_LABEL(num, name) +#endif +#endif +#ifndef LAST_CAS_READ_LABEL +#define LAST_CAS_READ_LABEL(num) +#endif + +#ifndef FIRST_FAI_READ_LABEL +#define FIRST_FAI_READ_LABEL(num) +#endif +#ifndef HANDLE_FAI_READ_LABEL +#ifndef HANDLE_READ_LABEL +#define HANDLE_FAI_READ_LABEL(num, name) +#else +#define HANDLE_FAI_READ_LABEL(num, name) HANDLE_READ_LABEL(num, name) +#endif +#endif +#ifndef LAST_FAI_READ_LABEL +#define LAST_FAI_READ_LABEL(num) +#endif + +#ifndef FIRST_WRITE_LABEL +#define FIRST_WRITE_LABEL(num) +#endif +#ifndef HANDLE_WRITE_LABEL +#ifndef HANDLE_MEMORY_LABEL +#define HANDLE_WRITE_LABEL(num, name) +#else +#define HANDLE_WRITE_LABEL(num, name) HANDLE_MEMORY_LABEL(num, name) +#endif +#endif +#ifndef LAST_WRITE_LABEL +#define LAST_WRITE_LABEL(num) +#endif + +#ifndef FIRST_CAS_WRITE_LABEL +#define FIRST_CAS_WRITE_LABEL(num) +#endif +#ifndef HANDLE_CAS_WRITE_LABEL +#ifndef HANDLE_WRITE_LABEL +#define HANDLE_CAS_WRITE_LABEL(num, name) +#else +#define HANDLE_CAS_WRITE_LABEL(num, name) HANDLE_WRITE_LABEL(num, name) +#endif +#endif +#ifndef LAST_CAS_WRITE_LABEL +#define LAST_CAS_WRITE_LABEL(num) +#endif + +#ifndef FIRST_FAI_WRITE_LABEL +#define FIRST_FAI_WRITE_LABEL(num) +#endif +#ifndef HANDLE_FAI_WRITE_LABEL +#ifndef HANDLE_WRITE_LABEL +#define HANDLE_FAI_WRITE_LABEL(num, name) +#else +#define HANDLE_FAI_WRITE_LABEL(num, name) HANDLE_WRITE_LABEL(num, name) +#endif +#endif +#ifndef LAST_FAI_WRITE_LABEL +#define LAST_FAI_WRITE_LABEL(num) +#endif + +#ifndef FIRST_FENCE_LABEL +#define FIRST_FENCE_LABEL(num) +#endif +#ifndef HANDLE_FENCE_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_FENCE_LABEL(num, name) +#else +#define HANDLE_FENCE_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_FENCE_LABEL +#define LAST_FENCE_LABEL(num) +#endif + +#ifndef FIRST_ALLOC_LABEL +#define FIRST_ALLOC_LABEL(num) +#endif +#ifndef HANDLE_ALLOC_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_ALLOC_LABEL(num, name) +#else +#define HANDLE_ALLOC_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_ALLOC_LABEL +#define LAST_ALLOC_LABEL(num) +#endif + +#ifndef FIRST_FREE_LABEL +#define FIRST_FREE_LABEL(num) +#endif +#ifndef HANDLE_FREE_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_FREE_LABEL(num, name) +#else +#define HANDLE_FREE_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_FREE_LABEL +#define LAST_FREE_LABEL(num) +#endif + +#ifndef FIRST_OTHER_LABEL +#define FIRST_OTHER_LABEL(num) +#endif +#ifndef HANDLE_OTHER_LABEL +#ifndef HANDLE_LABEL +#define HANDLE_OTHER_LABEL(num, name) +#else +#define HANDLE_OTHER_LABEL(num, name) HANDLE_LABEL(num, name) +#endif +#endif +#ifndef LAST_OTHER_LABEL +#define LAST_OTHER_LABEL(num) +#endif + +/* + * Begin labels - these denote the start of a given thread. + * A start might be the initial label (for main) or a start event (for others). + * Every thread has to have such a label. + */ +FIRST_BEGIN_LABEL(1) +HANDLE_BEGIN_LABEL(1, ThreadStart) +HANDLE_BEGIN_LABEL(2, Init) +LAST_BEGIN_LABEL(2) + +/* + * Terminator labels - these denote the termination of a thread. + * A termination might be a block label (denoting blockage), a kill label + * (denoting the reach of unrolling bound), or a finish label (normal termination). + * Block labels have different types, depending on the blockage. + */ +FIRST_TERM_LABEL(3) +FIRST_BLOCK_LABEL(3) +HANDLE_TERM_LABEL(3, SpinloopBlock) +HANDLE_TERM_LABEL(4, FaiZNEBlock) +HANDLE_TERM_LABEL(5, LockZNEBlock) +HANDLE_TERM_LABEL(6, HelpedCASBlock) +HANDLE_TERM_LABEL(7, ConfirmationBlock) +HANDLE_TERM_LABEL(8, LockNotAcqBlock) +HANDLE_TERM_LABEL(9, LockNotRelBlock) +HANDLE_TERM_LABEL(10, BarrierBlock) +HANDLE_TERM_LABEL(11, ErrorBlock) +HANDLE_TERM_LABEL(12, UserBlock) +HANDLE_TERM_LABEL(13, JoinBlock) +HANDLE_TERM_LABEL(14, ReadOptBlock) +LAST_BLOCK_LABEL(14) +HANDLE_TERM_LABEL(15, ThreadKill) +HANDLE_TERM_LABEL(16, ThreadFinish) +LAST_TERM_LABEL(16) + +/* + * Memory labels - these denote memory accesses. + * They are further divided into read and write labels, + * which in turn might be either plain, CAS or FAI. + */ +FIRST_MEMORY_LABEL(17) + +FIRST_READ_LABEL(17) + +HANDLE_READ_LABEL(17, Read) +HANDLE_READ_LABEL(18, BWaitRead) +HANDLE_READ_LABEL(19, SpeculativeRead) +HANDLE_READ_LABEL(20, ConfirmingRead) +HANDLE_READ_LABEL(21, CondVarWaitRead) + +FIRST_CAS_READ_LABEL(22) +HANDLE_CAS_READ_LABEL(22, CasRead) +HANDLE_CAS_READ_LABEL(23, LockCasRead) +HANDLE_CAS_READ_LABEL(24, TrylockCasRead) +HANDLE_CAS_READ_LABEL(25, HelpedCasRead) +HANDLE_CAS_READ_LABEL(26, ConfirmingCasRead) +LAST_CAS_READ_LABEL(26) + +FIRST_FAI_READ_LABEL(27) +HANDLE_FAI_READ_LABEL(27, FaiRead) +HANDLE_FAI_READ_LABEL(28, NoRetFaiRead) +HANDLE_FAI_READ_LABEL(29, BIncFaiRead) +LAST_FAI_READ_LABEL(29) + +LAST_READ_LABEL(29) + +FIRST_WRITE_LABEL(30) + +HANDLE_WRITE_LABEL(30, Write) +HANDLE_WRITE_LABEL(31, UnlockWrite) +HANDLE_WRITE_LABEL(32, BInitWrite) +HANDLE_WRITE_LABEL(33, BDestroyWrite) +HANDLE_WRITE_LABEL(34, CondVarInitWrite) +HANDLE_WRITE_LABEL(35, CondVarSignalWrite) +HANDLE_WRITE_LABEL(36, CondVarBcastWrite) +HANDLE_WRITE_LABEL(37, CondVarDestroyWrite) + +FIRST_CAS_WRITE_LABEL(38) +HANDLE_CAS_WRITE_LABEL(38, CasWrite) +HANDLE_CAS_WRITE_LABEL(39, LockCasWrite) +HANDLE_CAS_WRITE_LABEL(40, TrylockCasWrite) +HANDLE_CAS_WRITE_LABEL(41, HelpedCasWrite) +HANDLE_CAS_WRITE_LABEL(42, ConfirmingCasWrite) +LAST_CAS_WRITE_LABEL(42) + +FIRST_FAI_WRITE_LABEL(43) +HANDLE_FAI_WRITE_LABEL(43, FaiWrite) +HANDLE_FAI_WRITE_LABEL(44, NoRetFaiWrite) +HANDLE_FAI_WRITE_LABEL(45, BIncFaiWrite) +LAST_FAI_WRITE_LABEL(45) + +LAST_WRITE_LABEL(45) + +LAST_MEMORY_LABEL(45) + +/* + * Fence labels - these represent a memory fence. + */ +FIRST_FENCE_LABEL(46) +HANDLE_MEMORY_LABEL(46, Fence) +LAST_FENCE_LABEL(46) + +/* + * Alloc labels - these represent memory allocation. + */ +FIRST_ALLOC_LABEL(47) +HANDLE_ALLOC_LABEL(47, Malloc) +LAST_ALLOC_LABEL(47) + +/* + * Free labels - these represent memory deallocation. + */ +FIRST_FREE_LABEL(48) +HANDLE_FREE_LABEL(48, Free) +HANDLE_FREE_LABEL(49, HpRetire) +LAST_FREE_LABEL(49) + +/* + * Other labels - other operations that GenMC needs to track. + */ +FIRST_OTHER_LABEL(50) +HANDLE_OTHER_LABEL(50, ThreadCreate) +HANDLE_OTHER_LABEL(51, ThreadJoin) +HANDLE_OTHER_LABEL(52, HpProtect) +HANDLE_OTHER_LABEL(53, HelpingCas) +HANDLE_OTHER_LABEL(54, Optional) +HANDLE_OTHER_LABEL(55, LoopBegin) +HANDLE_OTHER_LABEL(56, SpinStart) +HANDLE_OTHER_LABEL(57, FaiZNESpinEnd) +HANDLE_OTHER_LABEL(58, LockZNESpinEnd) +HANDLE_OTHER_LABEL(59, Empty) +LAST_OTHER_LABEL(59) + +#undef FIRST_BEGIN_LABEL +#undef HANDLE_BEGIN_LABEL +#undef LAST_BEGIN_LABEL + +#undef FIRST_TERM_LABEL +#undef HANDLE_TERM_LABEL +#undef LAST_TERM_LABEL + +#undef FIRST_BLOCK_LABEL +#undef HANDLE_BLOCK_LABEL +#undef LAST_BLOCK_LABEL + +#undef FIRST_MEMORY_LABEL +#undef HANDLE_MEMORY_LABEL +#undef LAST_MEMORY_LABEL + +#undef FIRST_READ_LABEL +#undef HANDLE_READ_LABEL +#undef LAST_READ_LABEL + +#undef FIRST_CAS_READ_LABEL +#undef HANDLE_CAS_READ_LABEL +#undef LAST_CAS_READ_LABEL + +#undef FIRST_FAI_READ_LABEL +#undef HANDLE_FAI_READ_LABEL +#undef LAST_FAI_READ_LABEL + +#undef FIRST_WRITE_LABEL +#undef HANDLE_WRITE_LABEL +#undef LAST_WRITE_LABEL + +#undef FIRST_CAS_WRITE_LABEL +#undef HANDLE_CAS_WRITE_LABEL +#undef LAST_CAS_WRITE_LABEL + +#undef FIRST_FAI_WRITE_LABEL +#undef HANDLE_FAI_WRITE_LABEL +#undef LAST_FAI_WRITE_LABEL + +#undef FIRST_FENCE_LABEL +#undef HANDLE_FENCE_LABEL +#undef LAST_FENCE_LABEL + +#undef FIRST_ALLOC_LABEL +#undef HANDLE_ALLOC_LABEL +#undef LAST_ALLOC_LABEL + +#undef FIRST_FREE_LABEL +#undef HANDLE_FREE_LABEL +#undef LAST_FREE_LABEL + +#undef FIRST_OTHER_LABEL +#undef HANDLE_OTHER_LABEL +#undef LAST_OTHER_LABEL + +#ifdef HANDLE_LABEL +#undef HANDLE_LABEL +#endif diff --git a/src/EventLabel.hpp b/src/ExecutionGraph/EventLabel.hpp similarity index 51% rename from src/EventLabel.hpp rename to src/ExecutionGraph/EventLabel.hpp index cf1d97d..ebb6803 100644 --- a/src/EventLabel.hpp +++ b/src/ExecutionGraph/EventLabel.hpp @@ -18,25 +18,26 @@ * Author: Michalis Kokologiannakis */ -#ifndef __EVENTLABEL_HPP__ -#define __EVENTLABEL_HPP__ - -#include "DepInfo.hpp" -#include "DepView.hpp" -#include "Event.hpp" -#include "EventAttr.hpp" -#include "InterpreterEnumAPI.hpp" -#include "MemAccess.hpp" -#include "ModuleID.hpp" -#include "NameInfo.hpp" -#include "SAddr.hpp" -#include "SExpr.hpp" -#include "SVal.hpp" -#include "Stamp.hpp" -#include "ThreadInfo.hpp" -#include "VSet.hpp" -#include "View.hpp" -#include "value_ptr.hpp" +#ifndef GENMC_EVENTLABEL_HPP +#define GENMC_EVENTLABEL_HPP + +#include "ADT/DepView.hpp" +#include "ADT/VSet.hpp" +#include "ADT/View.hpp" +#include "ADT/value_ptr.hpp" +#include "ExecutionGraph/DepInfo.hpp" +#include "ExecutionGraph/Event.hpp" +#include "ExecutionGraph/EventAttr.hpp" +#include "ExecutionGraph/Stamp.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/ModuleID.hpp" +#include "Support/MemAccess.hpp" +#include "Support/NameInfo.hpp" +#include "Support/SAddr.hpp" +#include "Support/SExpr.hpp" +#include "Support/SVal.hpp" +#include "Support/ThreadInfo.hpp" +#include #include /* For AtomicOrdering in older LLVMs */ #include #include @@ -44,6 +45,10 @@ class DskAccessLabel; class ReadLabel; +class MallocLabel; +class FreeLabel; +class ThreadJoinLabel; +class ExecutionGraph; template class CopyableIList : public llvm::simple_ilist { @@ -70,105 +75,14 @@ class CopyableIList : public llvm::simple_ilist { * getter methods are private. One can obtain information about such relations * by querying the execution graph. */ -class EventLabel { +class EventLabel : public llvm::ilist_node { public: /* Discriminator for LLVM-style RTTI (dyn_cast<> et al). * It is public to allow clients perform a switch() on it */ enum EventLabelKind { - EL_Empty, - EL_Optional, - - EL_ThreadStart, - EL_Init, - EL_ThreadStartEnd, - - EL_TerminatorBegin, - EL_BlockBegin, - EL_SpinloopBlock, - EL_FaiZNEBlock, - EL_LockZNEBlock, - EL_HelpedCASBlock, - EL_ConfirmationBlock, - EL_LockNotAcqBlock, - EL_LockNotRelBlock, - EL_BarrierBlock, - EL_ErrorBlock, - EL_UserBlock, - EL_JoinBlock, - EL_ReadOptBlock, - EL_BlockEnd, - EL_ThreadKill, - EL_ThreadFinish, - EL_TerminatorLast, - - EL_ThreadCreate, - EL_ThreadJoin, - EL_LoopBegin, - EL_SpinStart, - EL_FaiZNESpinEnd, - EL_LockZNESpinEnd, - - EL_MemAccessBegin, - EL_Read, - EL_BWaitRead, - EL_SpeculativeRead, - EL_ConfirmingRead, - EL_FaiRead, - EL_NoRetFaiRead, - EL_BIncFaiRead, - EL_FaiReadLast, - EL_CasRead, - EL_LockCasRead, - EL_TrylockCasRead, - EL_HelpedCasRead, - EL_ConfirmingCasRead, - EL_CasReadLast, - EL_DskRead, - EL_LastRead, - EL_Write, - EL_UnlockWrite, - EL_BInitWrite, - EL_BDestroyWrite, - EL_FaiWrite, - EL_NoRetFaiWrite, - EL_BIncFaiWrite, - EL_FaiWriteLast, - EL_CasWrite, - EL_LockCasWrite, - EL_TrylockCasWrite, - EL_HelpedCasWrite, - EL_ConfirmingCasWrite, - EL_CasWriteLast, - EL_DskWrite, - EL_DskMdWrite, - EL_DskJnlWrite, - EL_DskDirWrite, - EL_LastDskWrite, - EL_LastWrite, - EL_MemAccessEnd, - - EL_Fence, - EL_DskFsync, - EL_DskSync, - EL_DskPbarrier, - EL_SmpFenceLKMM, - EL_RCUSyncLKMM, - EL_LastFence, - - EL_Malloc, - EL_Free, - EL_HpRetire, - EL_FreeLast, - - EL_HpProtect, - EL_LockLAPOR, - EL_UnlockLAPOR, - EL_HelpingCas, - EL_DskOpen, - EL_RCULockLKMM, - EL_RCUUnlockLKMM, - EL_CLFlush, +#define HANDLE_LABEL(NUM, NAME) NAME = NUM, +#include "ExecutionGraph/EventLabel.def" }; protected: @@ -202,6 +116,13 @@ class EventLabel { /* Returns the discriminator of this object */ EventLabelKind getKind() const { return kind; } + /* Returns the parent graph of this label */ + const ExecutionGraph *getParent() const { return parent; } + ExecutionGraph *getParent() { return parent; } + + /* Sets the parent graph for this label */ + void setParent(ExecutionGraph *graph) { parent = graph; } + /* Returns the position in the execution graph (thread, index) */ Event getPos() const { return position; } Event &getPos() { return position; } @@ -245,19 +166,20 @@ class EventLabel { void setCalculated(std::vector> &&calc) { calculatedRels = std::move(calc); } void setViews(std::vector &&views) { calculatedViews = std::move(views); } + void addView(View &&view) { calculatedViews.emplace_back(view); } /* Iterators for calculated relations */ calc_const_range calculated(size_t i) const { - return (getPos().isInitializer() || getKind() == EL_Empty) ? calculatedRels[0] - : calculatedRels[i]; + return (getPos().isInitializer() || getKind() == Empty) ? calculatedRels[0] + : calculatedRels[i]; } /* Getters for calculated views */ const View &view(size_t i) const { - return (getPos().isInitializer() || getKind() == EL_Empty) ? calculatedViews[0] - : calculatedViews[i]; + return (getPos().isInitializer() || getKind() == Empty) ? calculatedViews[0] + : calculatedViews[i]; } /* Returns true if this label corresponds to a non-atomic access */ @@ -298,15 +220,15 @@ class EventLabel { /* Returns true if this is a sequentially consistent access */ bool isSC() const { return ordering == llvm::AtomicOrdering::SequentiallyConsistent; } - /* Whether this label denotes the end of a thread */ - bool isTerminator() const { return isTerminator(getKind()); } - /* Whether this label can have outgoing dep edges */ bool isDependable() const { return isDependable(getKind()); } /* Whether this label carries a value */ bool hasValue() const { return hasValue(getKind()); } + /* Whether this label has a location */ + bool hasLocation() const { return hasLocation(getKind()); } + /* Returns true if this event can be revisited */ bool isRevisitable() const { return revisitable; } @@ -328,6 +250,7 @@ class EventLabel { /* Resets all graph-related info on a label to their default values */ virtual void reset() { + parent = nullptr; stamp = std::nullopt; calculatedRels.clear(); calculatedViews.clear(); @@ -341,28 +264,17 @@ class EventLabel { friend class ExecutionGraph; friend class DepExecutionGraph; - static inline bool isTerminator(EventLabelKind k) - { - return (k >= EL_TerminatorBegin && k <= EL_TerminatorLast); - } - - static inline bool isDependable(EventLabelKind k) - { - return (k >= EL_Read && k <= EL_LastRead) || k == EL_Malloc; - } - - static inline bool hasValue(EventLabelKind k) - { - return (k >= EL_Read && k <= EL_LastRead) || - (k >= EL_ThreadStart && k <= EL_ThreadStartEnd) || k == EL_ThreadJoin || - k == EL_Optional; - } + static inline bool isDependable(EventLabelKind k); + static inline bool hasValue(EventLabelKind k); + static inline bool hasLocation(EventLabelKind k); void setStamp(Stamp s) { stamp = s; } /* Discriminator enum for LLVM-style RTTI */ const EventLabelKind kind; + ExecutionGraph *parent{}; + /* Position of this label within the execution graph (thread, index) */ Event position; @@ -388,81 +300,143 @@ class EventLabel { }; #define DEFINE_CREATE_CLONE(name) \ - template static std::unique_ptr create(Ts &&...params) \ + template static std::unique_ptr create(Ts &&...params) \ { \ - return std::make_unique(std::forward(params)...); \ + return std::make_unique(std::forward(params)...); \ } \ \ - std::unique_ptr clone() const override { return std::make_unique(*this); } + std::unique_ptr clone() const override \ + { \ + return std::make_unique(*this); \ + } + +#define DEFINE_STANDARD_MEMBERS(name) \ + DEFINE_CREATE_CLONE(name) \ + \ + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ + static bool classofKind(EventLabelKind k) { return k == name; } /******************************************************************************* - ** DskAccessLabel Class + ** ThreadStartLabel Class ******************************************************************************/ -/* This is used only as base class of specific labels that - * model disk accesses. These labels are (only the top classes that directly - * derive from EventLabel are listed, not their subclasses): - * - * DskReadLabel - * DskWriteLabel - * DskSyncLabel - * DskFsyncLabel - * DskPbarrierLabel - * - * Note: This is not a child of EventLabel to avoid virtual inheritance */ -class DskAccessLabel { +/* Represents the beginning of a thread. This label synchronizes with the + * ThreadCreateLabel that led to the creation of this thread */ +class ThreadStartLabel : public EventLabel { protected: - DskAccessLabel(EventLabel::EventLabelKind k) : eventLabelKind(k) {} + ThreadStartLabel(EventLabelKind kind, Event pos, Event pc) + : EventLabel(kind, pos, llvm::AtomicOrdering::Acquire, EventDeps()), + parentCreate(pc), threadInfo() + {} public: - /* Getter/setter for a view representing (a subset of) - * events that have persisted before this disk access */ - const DepView &getPbView() const { return pbView; } - void setPbView(DepView &&v) { pbView = std::move(v); } + ThreadStartLabel(Event pos, llvm::AtomicOrdering ord, Event pc, ThreadInfo tinfo, + int symm = -1) + : EventLabel(ThreadStart, pos, ord, EventDeps()), parentCreate(pc), + threadInfo(tinfo), symmetricTid(symm) + {} + ThreadStartLabel(Event pos, Event pc, ThreadInfo tinfo, int symm = -1) + : ThreadStartLabel(pos, llvm::AtomicOrdering::Acquire, pc, tinfo, symm) + {} + + /* Returns the position of the corresponding create operation */ + Event getParentCreate() const { return parentCreate; } + + /* Getters for the thread's info */ + const ThreadInfo &getThreadInfo() const { return threadInfo; } + ThreadInfo &getThreadInfo() { return threadInfo; } - EventLabel::EventLabelKind getEventLabelKind() const { return eventLabelKind; } + /* SR: Returns the id of a symmetric thread, or -1 if no symmetric thread exists */ + int getSymmetricTid() const { return symmetricTid; } - virtual void reset() { pbView.clear(); } + DEFINE_CREATE_CLONE(ThreadStart) - static bool classof(const EventLabel *lab) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } + static bool classofKind(EventLabelKind k) { - return lab->getKind() == EventLabel::EL_DskRead || - (lab->getKind() >= EventLabel::EL_DskWrite && - lab->getKind() <= EventLabel::EL_LastDskWrite) || - lab->getKind() == EventLabel::EL_DskSync || - lab->getKind() == EventLabel::EL_DskFsync || - lab->getKind() == EventLabel::EL_DskPbarrier; + return +#define FIRST_BEGIN_LABEL(NUM) k >= NUM && +#define LAST_BEGIN_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" } private: - /* The EventLabel class that this disk access represents */ - EventLabel::EventLabelKind eventLabelKind; + /* The position of the corresponding create opeartion */ + Event parentCreate; + + /* Information about this thread */ + ThreadInfo threadInfo; - /* View indicating a _subset_ of the events that must have - * persisted before the access */ - DepView pbView; + /* SR: The tid a symmetric thread (currently: minimum among all) */ + int symmetricTid = -1; }; /******************************************************************************* - ** EmptyLabel Class + ** InitLabel Class ******************************************************************************/ -/* A plain empty label. This label type provides a good alternative to nullptr - * in graphs that track dependencies where the po-predecessors of a label might - * not exist (or might have been removed). It also does not break LLVM-style - * RTTI, in contrast to nullptr */ -class EmptyLabel : public EventLabel { +/* Represents the INIT label of the graph, modeling the initialization of all + * memory locaitons. The first thread is special in that it does not start with + * a ThreadStartLabel as the other threads do */ +class InitLabel : public ThreadStartLabel { + +private: + using ReaderList = CopyableIList; + friend class ExecutionGraph; + friend class DepExecutionGraph; public: - EmptyLabel(Event pos) - : EventLabel(EL_Empty, pos, llvm::AtomicOrdering::NotAtomic, EventDeps()) - {} + InitLabel() : ThreadStartLabel(Init, Event::getInit(), Event::getInit()) {} + + using rf_iterator = ReaderList::iterator; + using const_rf_iterator = ReaderList::const_iterator; + + rf_iterator rf_begin(SAddr addr) { return initRfs[addr].begin(); } + const_rf_iterator rf_begin(SAddr addr) const { return initRfs.at(addr).begin(); }; + rf_iterator rf_end(SAddr addr) { return initRfs[addr].end(); } + const_rf_iterator rf_end(SAddr addr) const { return initRfs.at(addr).end(); } + + DEFINE_STANDARD_MEMBERS(Init) + +private: + void addReader(ReadLabel *rLab); + + /* Removes all readers that satisfy predicate F */ + template void removeReader(SAddr addr, F cond) + { + for (auto it = rf_begin(addr); it != rf_end(addr);) { + if (cond(*it)) + it = initRfs[addr].erase(it); + else + ++it; + } + } + + std::unordered_map initRfs; +}; + +/******************************************************************************* + ** TerminatorLabel Class + ******************************************************************************/ + +/* Abstract class for representing the termination of a thread */ +class TerminatorLabel : public EventLabel { - DEFINE_CREATE_CLONE(EmptyLabel) +protected: + TerminatorLabel(EventLabelKind k, llvm::AtomicOrdering ord, Event pos) + : EventLabel(k, pos, ord, EventDeps()) + {} +public: static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_Empty; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_TERM_LABEL(NUM) k >= NUM && +#define LAST_TERM_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } }; /******************************************************************************* @@ -470,40 +444,43 @@ class EmptyLabel : public EventLabel { ******************************************************************************/ /* An abstract label that represents a blockage. Subclasses denote the blockage type */ -class BlockLabel : public EventLabel { +class BlockLabel : public TerminatorLabel { protected: BlockLabel(EventLabelKind k, Event pos) - : EventLabel(k, pos, llvm::AtomicOrdering::NotAtomic, EventDeps()) + : TerminatorLabel(k, llvm::AtomicOrdering::NotAtomic, pos) {} public: static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_BlockBegin && k <= EL_BlockEnd; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_BLOCK_LABEL(NUM) k >= NUM && +#define LAST_BLOCK_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } }; -#define BLOCK_PURE_SUBCLASS(_class_kind) \ - class _class_kind##BlockLabel : public BlockLabel { \ +#define BLOCK_PURE_SUBCLASS(name) \ + class name##Label : public BlockLabel { \ \ public: \ - _class_kind##BlockLabel(Event pos) : BlockLabel(EL_##_class_kind##Block, pos) {} \ - \ - DEFINE_CREATE_CLONE(_class_kind##BlockLabel) \ + name##Label(Event pos) : BlockLabel(name, pos) {} \ \ - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ - static bool classofKind(EventLabelKind k) { return k == EL_##_class_kind##Block; } \ + DEFINE_STANDARD_MEMBERS(name) \ }; -BLOCK_PURE_SUBCLASS(Spinloop); -BLOCK_PURE_SUBCLASS(FaiZNE); -BLOCK_PURE_SUBCLASS(LockZNE); -BLOCK_PURE_SUBCLASS(HelpedCAS); -BLOCK_PURE_SUBCLASS(Confirmation); -BLOCK_PURE_SUBCLASS(LockNotAcq); -BLOCK_PURE_SUBCLASS(LockNotRel); -BLOCK_PURE_SUBCLASS(Barrier); -BLOCK_PURE_SUBCLASS(Error); -BLOCK_PURE_SUBCLASS(User); +BLOCK_PURE_SUBCLASS(SpinloopBlock); +BLOCK_PURE_SUBCLASS(FaiZNEBlock); +BLOCK_PURE_SUBCLASS(LockZNEBlock); +BLOCK_PURE_SUBCLASS(HelpedCASBlock); +BLOCK_PURE_SUBCLASS(ConfirmationBlock); +BLOCK_PURE_SUBCLASS(LockNotAcqBlock); +BLOCK_PURE_SUBCLASS(LockNotRelBlock); +BLOCK_PURE_SUBCLASS(BarrierBlock); +BLOCK_PURE_SUBCLASS(ErrorBlock); +BLOCK_PURE_SUBCLASS(UserBlock); /* * Represents that a thread cannot be scheduled until a child @@ -513,16 +490,12 @@ BLOCK_PURE_SUBCLASS(User); class JoinBlockLabel : public BlockLabel { public: - JoinBlockLabel(Event pos, unsigned childId) - : BlockLabel(EL_JoinBlock, pos), childId(childId) + JoinBlockLabel(Event pos, unsigned childId) : BlockLabel(JoinBlock, pos), childId(childId) {} const unsigned &getChildId() const { return childId; } - DEFINE_CREATE_CLONE(JoinBlockLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_JoinBlock; } + DEFINE_STANDARD_MEMBERS(JoinBlock) private: const unsigned int childId{}; // the child waiting on @@ -537,125 +510,78 @@ class JoinBlockLabel : public BlockLabel { class ReadOptBlockLabel : public BlockLabel { public: - ReadOptBlockLabel(Event pos, SAddr addr) : BlockLabel(EL_ReadOptBlock, pos), addr(addr) {} + ReadOptBlockLabel(Event pos, SAddr addr) : BlockLabel(ReadOptBlock, pos), addr(addr) {} const SAddr &getAddr() const { return addr; } - DEFINE_CREATE_CLONE(ReadOptBlockLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_ReadOptBlock; } + DEFINE_STANDARD_MEMBERS(ReadOptBlock) private: SAddr addr; // the address waiting on }; /******************************************************************************* - ** OptionalLabel Class - ******************************************************************************/ - -/* A label that represents the beginning of an optional block */ -class OptionalLabel : public EventLabel { - -public: - OptionalLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_Optional, pos, llvm::AtomicOrdering::NotAtomic, deps) - {} - - /* Whether this block is expandable */ - bool isExpandable() const { return expandable; } - void setExpandable(bool exp) { expandable = exp; } - - /* Whether this block has been expanded */ - bool isExpanded() const { return expanded; } - void setExpanded(bool exp) { expanded = exp; } - - DEFINE_CREATE_CLONE(OptionalLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_Optional; } - -private: - bool expandable = true; - bool expanded = false; -}; - -/******************************************************************************* - ** LoopBeginLabel Class + ** ThreadKillLabel Class ******************************************************************************/ -/* A label that marks the beginning of a spinloop. Used in DSA. */ -class LoopBeginLabel : public EventLabel { +/* Represents the abnormal termination of a thread */ +class ThreadKillLabel : public TerminatorLabel { public: - LoopBeginLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_LoopBegin, pos, llvm::AtomicOrdering::NotAtomic, deps) + ThreadKillLabel(Event pos) + : TerminatorLabel(ThreadKill, llvm::AtomicOrdering::NotAtomic, pos) {} - DEFINE_CREATE_CLONE(LoopBeginLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_LoopBegin; } + DEFINE_STANDARD_MEMBERS(ThreadKill) }; /******************************************************************************* - ** SpinStartLabel Class + ** ThreadFinishLabel Class ******************************************************************************/ -/* A label that marks the beginning of a spinloop iteration. It is meant - * to be used by the liveness (await-termination) checks. */ -class SpinStartLabel : public EventLabel { +/* Represents the ending of a thread. This label synchronizes with the + * ThreadJoinLabel that awaits for this particular thread (if any) + * + * FIXME: no error is reported if multiple threads are waiting on the + * same thread */ +class ThreadFinishLabel : public TerminatorLabel { public: - SpinStartLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_SpinStart, pos, llvm::AtomicOrdering::NotAtomic, deps) + ThreadFinishLabel(Event pos, llvm::AtomicOrdering ord, SVal retVal) + : TerminatorLabel(ThreadFinish, ord, pos), retVal(retVal) {} - DEFINE_CREATE_CLONE(SpinStartLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_SpinStart; } -}; - -/******************************************************************************* - ** FaiZNESpinEndLabel Class - ******************************************************************************/ - -/* A label that marks the end of a potential FaiZNE spinloop. If the loop turns out to be not - * a spinloop, it is added to the graph; otherwise, it should be replaced by a BlockLabel */ -class FaiZNESpinEndLabel : public EventLabel { - -public: - FaiZNESpinEndLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_FaiZNESpinEnd, pos, llvm::AtomicOrdering::NotAtomic, deps) + ThreadFinishLabel(Event pos, SVal retVal) + : ThreadFinishLabel(pos, llvm::AtomicOrdering::Release, retVal) {} - DEFINE_CREATE_CLONE(FaiZNESpinEndLabel) + /* Returns the join() operation waiting on this thread or + NULL if no such operation exists (yet) */ + ThreadJoinLabel *getParentJoin() const { return parentJoin; } - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_FaiZNESpinEnd; } -}; + /* Sets the corresponding join() event */ + void setParentJoin(ThreadJoinLabel *jLab) { parentJoin = jLab; } -/******************************************************************************* - ** LockZNESpinEndLabel Class - ******************************************************************************/ + /* Returns the return value of this thread */ + SVal getRetVal() const { return retVal; } -/* A label that marks the end of a potential LockZNE spinloop */ -class LockZNESpinEndLabel : public EventLabel { + virtual void reset() override + { + EventLabel::reset(); + parentJoin = nullptr; + } -public: - LockZNESpinEndLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_LockZNESpinEnd, pos, llvm::AtomicOrdering::NotAtomic, deps) - {} + DEFINE_STANDARD_MEMBERS(ThreadFinish) - DEFINE_CREATE_CLONE(LockZNESpinEndLabel) +private: + /* Position of corresponding join() event in the graph + * (NULL if such event does not exist) */ + ThreadJoinLabel *parentJoin = nullptr; - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_LockZNESpinEnd; } + /* Return value of the thread */ + SVal retVal; }; -class MallocLabel; - /******************************************************************************* ** MemAccessLabel Class (Abstract) ******************************************************************************/ @@ -707,7 +633,10 @@ class MemAccessLabel : public EventLabel, public llvm::ilist_nodegetKind()); } static bool classofKind(EventLabelKind k) { - return k >= EL_MemAccessBegin && k <= EL_MemAccessEnd; + return +#define FIRST_MEMORY_LABEL(NUM) k >= NUM && +#define LAST_MEMORY_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" } private: @@ -744,7 +673,7 @@ class ReadLabel : public MemAccessLabel, public llvm::ilist_node { public: ReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, EventLabel *rfLab, AnnotVP annot, const EventDeps &deps = EventDeps()) - : ReadLabel(EL_Read, pos, ord, loc, size, type, rfLab, annot, deps) + : ReadLabel(Read, pos, ord, loc, size, type, rfLab, annot, deps) {} ReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, EventLabel *rfLab, const EventDeps &deps = EventDeps()) @@ -755,8 +684,6 @@ class ReadLabel : public MemAccessLabel, public llvm::ilist_node { : ReadLabel(pos, ord, loc, size, type, nullptr, nullptr, deps) {} - DEFINE_CREATE_CLONE(ReadLabel) - /* Returns the position of the write this read is readinf-from */ EventLabel *getRf() const { return readsFrom; } EventLabel *getRf() { return readsFrom; } @@ -781,6 +708,9 @@ class ReadLabel : public MemAccessLabel, public llvm::ilist_node { /* Sets the IPR status for this read */ void setIPRStatus(bool status) { ipr = status; } + /* Helper: Whether this is a confirmation read */ + bool isConfirming() const { return isConfirming(getKind()); } + /* SAVer: Getter/setter for the annotation expression */ const AnnotT *getAnnot() const { return annotExpr.get(); } void setAnnot(std::unique_ptr annot) { annotExpr = std::move(annot); } @@ -792,10 +722,20 @@ class ReadLabel : public MemAccessLabel, public llvm::ilist_node { ipr = false; } + DEFINE_CREATE_CLONE(Read) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_Read && k <= EL_LastRead; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_READ_LABEL(NUM) k >= NUM && +#define LAST_READ_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: + static inline bool isConfirming(EventLabelKind k); + friend class ExecutionGraph; friend class DepExecutionGraph; @@ -805,72 +745,42 @@ class ReadLabel : public MemAccessLabel, public llvm::ilist_node { void setRf(EventLabel *rfLab) { readsFrom = rfLab; } /* Position of the write it is reading from in the graph */ - EventLabel *readsFrom; + EventLabel *readsFrom = nullptr; /* Whether the read has been revisited in place */ - bool ipr; + bool ipr = false; /* SAVer: Expression for annotatable loads. This needs to have * heap-value semantics so that it does not create concurrency issues */ - AnnotVP annotExpr; + AnnotVP annotExpr = nullptr; }; -#define READ_PURE_SUBCLASS(_class_kind) \ - class _class_kind##ReadLabel : public ReadLabel { \ +#define READ_PURE_SUBCLASS(name) \ + class name##Label : public ReadLabel { \ \ public: \ - _class_kind##ReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ - AType type, EventLabel *rfLab, AnnotVP annot, \ - const EventDeps &deps = EventDeps()) \ - : ReadLabel(EL_##_class_kind##Read, pos, ord, loc, size, type, rfLab, \ - std::move(annot), deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ + AType type, EventLabel *rfLab, AnnotVP annot, \ + const EventDeps &deps = EventDeps()) \ + : ReadLabel(name, pos, ord, loc, size, type, rfLab, std::move(annot), \ + deps) \ {} \ - _class_kind##ReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ - AType type, EventLabel *rfLab, \ - const EventDeps &deps = EventDeps()) \ - : _class_kind##ReadLabel(pos, ord, loc, size, type, rfLab, nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ + AType type, EventLabel *rfLab, const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, loc, size, type, rfLab, nullptr, deps) \ {} \ - _class_kind##ReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ - AType type, const EventDeps &deps = EventDeps()) \ - : _class_kind \ - ##ReadLabel(pos, ord, loc, size, type, nullptr, nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ + AType type, const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, loc, size, type, nullptr, nullptr, deps) \ {} \ \ - DEFINE_CREATE_CLONE(_class_kind##ReadLabel) \ - \ - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ - static bool classofKind(EventLabelKind k) { return k == EL_##_class_kind##Read; } \ + DEFINE_STANDARD_MEMBERS(name) \ }; -READ_PURE_SUBCLASS(Speculative); -READ_PURE_SUBCLASS(Confirming); - -/******************************************************************************* - ** BWaitReadLabel Class - ******************************************************************************/ - -/* Specialization of ReadLabel for the read part of a barrier_wait() op */ -class BWaitReadLabel : public ReadLabel { - -public: - BWaitReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, - EventLabel *rfLab, AnnotVP annot, const EventDeps &deps = EventDeps()) - : ReadLabel(EL_BWaitRead, pos, ord, loc, size, type, rfLab, std::move(annot), deps) - {} - BWaitReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, - EventLabel *rfLab, const EventDeps &deps = EventDeps()) - : BWaitReadLabel(pos, ord, loc, size, type, rfLab, nullptr, deps) - {} - BWaitReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, - const EventDeps &deps = EventDeps()) - : BWaitReadLabel(pos, ord, loc, size, type, nullptr, nullptr, deps) - {} - - DEFINE_CREATE_CLONE(BWaitReadLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_BWaitRead; } -}; +READ_PURE_SUBCLASS(SpeculativeRead); +READ_PURE_SUBCLASS(ConfirmingRead); +READ_PURE_SUBCLASS(BWaitRead); +READ_PURE_SUBCLASS(CondVarWaitRead); /******************************************************************************* ** FaiReadLabel Class @@ -892,7 +802,7 @@ class FaiReadLabel : public ReadLabel { FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, llvm::AtomicRMWInst::BinOp op, SVal val, WriteAttr wattr, EventLabel *rfLab, AnnotVP annot, const EventDeps &deps = EventDeps()) - : FaiReadLabel(EL_FaiRead, pos, ord, addr, size, type, op, val, wattr, rfLab, + : FaiReadLabel(FaiRead, pos, ord, addr, size, type, op, val, wattr, rfLab, std::move(annot), deps) {} FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, @@ -910,8 +820,6 @@ class FaiReadLabel : public ReadLabel { : FaiReadLabel(pos, ord, addr, size, type, op, val, WriteAttr::None, deps) {} - DEFINE_CREATE_CLONE(FaiReadLabel) - /* Returns the type of this RMW operation (e.g., add, sub) */ llvm::AtomicRMWInst::BinOp getOp() const { return binOp; } @@ -931,8 +839,16 @@ class FaiReadLabel : public ReadLabel { wattr &= ~(WriteAttr::RevBlocker); } + DEFINE_CREATE_CLONE(FaiRead) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_FaiRead && k <= EL_FaiReadLast; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_FAI_READ_LABEL(NUM) k >= NUM && +#define LAST_FAI_READ_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: /* The binary operator for this RMW operation */ @@ -942,52 +858,41 @@ class FaiReadLabel : public ReadLabel { SVal opValue; /* Attributes for the write part of the RMW */ - WriteAttr wattr; + WriteAttr wattr = WriteAttr::None; }; -#define FAIREAD_PURE_SUBCLASS(_class_kind) \ - class _class_kind##FaiReadLabel : public FaiReadLabel { \ +#define FAIREAD_PURE_SUBCLASS(name) \ + class name##Label : public FaiReadLabel { \ \ public: \ - _class_kind##FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, llvm::AtomicRMWInst::BinOp op, \ - SVal val, WriteAttr wattr, EventLabel *rfLab, \ - AnnotVP annot, const EventDeps &deps = EventDeps()) \ - : FaiReadLabel(EL_##_class_kind##FaiRead, pos, ord, addr, size, type, op, \ - val, wattr, rfLab, std::move(annot), deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, llvm::AtomicRMWInst::BinOp op, SVal val, WriteAttr wattr, \ + EventLabel *rfLab, AnnotVP annot, const EventDeps &deps = EventDeps()) \ + : FaiReadLabel(name, pos, ord, addr, size, type, op, val, wattr, rfLab, \ + std::move(annot), deps) \ {} \ - _class_kind##FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, llvm::AtomicRMWInst::BinOp op, \ - SVal val, WriteAttr wattr, EventLabel *rfLab, \ - const EventDeps &deps = EventDeps()) \ - : _class_kind##FaiReadLabel(pos, ord, addr, size, type, op, val, wattr, \ - rfLab, nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, llvm::AtomicRMWInst::BinOp op, SVal val, WriteAttr wattr, \ + EventLabel *rfLab, const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, addr, size, type, op, val, wattr, rfLab, nullptr, \ + deps) \ {} \ - _class_kind##FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, llvm::AtomicRMWInst::BinOp op, \ - SVal val, WriteAttr wattr, \ - const EventDeps &deps = EventDeps()) \ - : _class_kind##FaiReadLabel(pos, ord, addr, size, type, op, val, wattr, \ - nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, llvm::AtomicRMWInst::BinOp op, SVal val, WriteAttr wattr, \ + const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, addr, size, type, op, val, wattr, nullptr, deps) \ {} \ - _class_kind##FaiReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, llvm::AtomicRMWInst::BinOp op, \ - SVal val, const EventDeps &deps = EventDeps()) \ - : _class_kind##FaiReadLabel(pos, ord, addr, size, type, op, val, \ - WriteAttr::None, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, llvm::AtomicRMWInst::BinOp op, SVal val, \ + const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, addr, size, type, op, val, WriteAttr::None, deps) \ {} \ \ - DEFINE_CREATE_CLONE(_class_kind##FaiReadLabel) \ - \ - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ - static bool classofKind(EventLabelKind k) \ - { \ - return k == EL_##_class_kind##FaiRead; \ - } \ + DEFINE_STANDARD_MEMBERS(name) \ }; -FAIREAD_PURE_SUBCLASS(NoRet); -FAIREAD_PURE_SUBCLASS(BInc); +FAIREAD_PURE_SUBCLASS(NoRetFaiRead); +FAIREAD_PURE_SUBCLASS(BIncFaiRead); /******************************************************************************* ** CasReadLabel Class @@ -1008,7 +913,7 @@ class CasReadLabel : public ReadLabel { CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal exp, SVal swap, WriteAttr wattr, EventLabel *rfLab, AnnotVP annot, const EventDeps &deps = EventDeps()) - : CasReadLabel(EL_CasRead, pos, ord, addr, size, type, exp, swap, wattr, rfLab, + : CasReadLabel(CasRead, pos, ord, addr, size, type, exp, swap, wattr, rfLab, std::move(annot), deps) {} CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, @@ -1025,8 +930,6 @@ class CasReadLabel : public ReadLabel { : CasReadLabel(pos, ord, addr, size, type, exp, swap, WriteAttr::None, deps) {} - DEFINE_CREATE_CLONE(CasReadLabel) - /* Returns the value that will make this CAS succeed */ SVal getExpected() const { return expected; } @@ -1046,8 +949,16 @@ class CasReadLabel : public ReadLabel { wattr &= ~(WriteAttr::RevBlocker); } + DEFINE_CREATE_CLONE(CasRead) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_CasRead && k <= EL_CasReadLast; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_CAS_READ_LABEL(NUM) k >= NUM && +#define LAST_CAS_READ_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: /* The value that will make this CAS succeed */ @@ -1057,51 +968,41 @@ class CasReadLabel : public ReadLabel { const SVal swapValue; /* The attributes of the write part of the RMW */ - WriteAttr wattr; + WriteAttr wattr = WriteAttr::None; }; -#define CASREAD_PURE_SUBCLASS(_class_kind) \ - class _class_kind##CasReadLabel : public CasReadLabel { \ +#define CASREAD_PURE_SUBCLASS(name) \ + class name##Label : public CasReadLabel { \ \ public: \ - _class_kind##CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, SVal exp, SVal swap, \ - WriteAttr wattr, EventLabel *rfLab, AnnotVP annot, \ - const EventDeps &deps = EventDeps()) \ - : CasReadLabel(EL_##_class_kind##CasRead, pos, ord, addr, size, type, exp, \ - swap, wattr, rfLab, std::move(annot), deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, SVal exp, SVal swap, WriteAttr wattr, EventLabel *rfLab, \ + AnnotVP annot, const EventDeps &deps = EventDeps()) \ + : CasReadLabel(name, pos, ord, addr, size, type, exp, swap, wattr, rfLab, \ + std::move(annot), deps) \ {} \ - _class_kind##CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, SVal exp, SVal swap, \ - WriteAttr wattr, EventLabel *rfLab, \ - const EventDeps &deps = EventDeps()) \ - : _class_kind##CasReadLabel(pos, ord, addr, size, type, exp, swap, wattr, \ - rfLab, nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, SVal exp, SVal swap, WriteAttr wattr, EventLabel *rfLab, \ + const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, addr, size, type, exp, swap, wattr, rfLab, \ + nullptr, deps) \ {} \ - _class_kind##CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, SVal exp, SVal swap, \ - WriteAttr wattr, const EventDeps &deps = EventDeps()) \ - : _class_kind##CasReadLabel(pos, ord, addr, size, type, exp, swap, wattr, \ - nullptr, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, SVal exp, SVal swap, WriteAttr wattr, \ + const EventDeps &deps = EventDeps()) \ + : name##Label(pos, ord, addr, size, type, exp, swap, wattr, nullptr, deps) \ {} \ - _class_kind##CasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, SVal exp, SVal swap, \ - const EventDeps &deps = EventDeps()) \ - : _class_kind##CasReadLabel(pos, ord, addr, size, type, exp, swap, \ - WriteAttr::None, deps) \ + name##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, SVal exp, SVal swap, const EventDeps &deps = EventDeps()) \ + : name \ + ##Label(pos, ord, addr, size, type, exp, swap, WriteAttr::None, deps) \ {} \ \ - DEFINE_CREATE_CLONE(_class_kind##CasReadLabel) \ - \ - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ - static bool classofKind(EventLabelKind k) \ - { \ - return k == EL_##_class_kind##CasRead; \ - } \ + DEFINE_STANDARD_MEMBERS(name) \ }; -CASREAD_PURE_SUBCLASS(Helped); -CASREAD_PURE_SUBCLASS(Confirming); +CASREAD_PURE_SUBCLASS(HelpedCasRead); +CASREAD_PURE_SUBCLASS(ConfirmingCasRead); /******************************************************************************* ** LockCasReadLabel Class @@ -1114,7 +1015,7 @@ class LockCasReadLabel : public CasReadLabel { LockCasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal exp, SVal swap, WriteAttr wattr, EventLabel *rfLab, AnnotVP annot = nullptr, const EventDeps &deps = EventDeps()) - : CasReadLabel(EL_LockCasRead, pos, ord, addr, size, type, exp, swap, wattr, rfLab, + : CasReadLabel(LockCasRead, pos, ord, addr, size, type, exp, swap, wattr, rfLab, std::move(annot), deps) {} LockCasReadLabel(Event pos, SAddr addr, ASize size, WriteAttr wattr, EventLabel *rfLab, @@ -1131,10 +1032,7 @@ class LockCasReadLabel : public CasReadLabel { : LockCasReadLabel(pos, addr, size, WriteAttr::None, std::move(annot), deps) {} - DEFINE_CREATE_CLONE(LockCasReadLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_LockCasRead; } + DEFINE_STANDARD_MEMBERS(LockCasRead) }; /******************************************************************************* @@ -1148,8 +1046,8 @@ class TrylockCasReadLabel : public CasReadLabel { TrylockCasReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal exp, SVal swap, WriteAttr wattr, EventLabel *rfLab, AnnotVP annot = nullptr, const EventDeps &deps = EventDeps()) - : CasReadLabel(EL_TrylockCasRead, pos, ord, addr, size, type, exp, swap, wattr, - rfLab, std::move(annot), deps) + : CasReadLabel(TrylockCasRead, pos, ord, addr, size, type, exp, swap, wattr, rfLab, + std::move(annot), deps) {} TrylockCasReadLabel(Event pos, SAddr addr, ASize size, WriteAttr wattr, EventLabel *rfLab, AnnotVP annot = nullptr, const EventDeps &deps = EventDeps()) @@ -1165,49 +1063,7 @@ class TrylockCasReadLabel : public CasReadLabel { : TrylockCasReadLabel(pos, addr, size, WriteAttr::None, std::move(annot), deps) {} - DEFINE_CREATE_CLONE(TrylockCasReadLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_TrylockCasRead; } -}; - -/******************************************************************************* - ** DskReadLabel Class - ******************************************************************************/ - -/* Models a read from the disk (e.g., via read()) */ -class DskReadLabel : public ReadLabel, public DskAccessLabel { - -public: - DskReadLabel(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, AType type, - EventLabel *rfLab = nullptr, const EventDeps &deps = EventDeps()) - : ReadLabel(EL_DskRead, pos, ord, loc, size, type, rfLab, nullptr, deps), - DskAccessLabel(EL_DskRead) - {} - - DskReadLabel(Event pos, SAddr loc, ASize size, AType type, EventLabel *rfLab = nullptr, - const EventDeps &deps = EventDeps()) - : DskReadLabel(pos, llvm::AtomicOrdering::Acquire, loc, size, type, rfLab, deps) - {} - - DEFINE_CREATE_CLONE(DskReadLabel) - - virtual void reset() override - { - ReadLabel::reset(); - DskAccessLabel::reset(); - } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskRead; } - static DskAccessLabel *castToDskAccessLabel(const DskReadLabel *D) - { - return static_cast(const_cast(D)); - } - static DskReadLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } + DEFINE_STANDARD_MEMBERS(TrylockCasRead) }; /******************************************************************************* @@ -1231,15 +1087,13 @@ class WriteLabel : public MemAccessLabel, public llvm::ilist_node { public: WriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr, const EventDeps &deps = EventDeps()) - : WriteLabel(EL_Write, pos, ord, addr, size, type, val, wattr, deps) + : WriteLabel(Write, pos, ord, addr, size, type, val, wattr, deps) {} WriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, const EventDeps &deps = EventDeps()) : WriteLabel(pos, ord, addr, size, type, val, WriteAttr::None, deps) {} - DEFINE_CREATE_CLONE(WriteLabel) - /* Getter/setter for the write value */ SVal getVal() const { return value; } void setVal(SVal v) { value = v; } @@ -1276,8 +1130,16 @@ class WriteLabel : public MemAccessLabel, public llvm::ilist_node { wattr &= ~(WriteAttr::RevBlocker); } + DEFINE_CREATE_CLONE(Write) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_Write && k <= EL_LastWrite; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_WRITE_LABEL(NUM) k >= NUM && +#define LAST_WRITE_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: friend class ExecutionGraph; @@ -1310,69 +1172,34 @@ class WriteLabel : public MemAccessLabel, public llvm::ilist_node { ReaderList readerList; /* Attributes of the write */ - WriteAttr wattr; + WriteAttr wattr = WriteAttr::None; }; -/******************************************************************************* - ** UnlockWriteLabel Class - ******************************************************************************/ - -/* Specialization of writes for unlock events */ -class UnlockWriteLabel : public WriteLabel { - -public: - UnlockWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, const EventDeps &deps = EventDeps()) - : WriteLabel(EL_UnlockWrite, pos, ord, addr, size, type, val, deps) - {} - UnlockWriteLabel(Event pos, SAddr addr, ASize size, const EventDeps &deps = EventDeps()) - : UnlockWriteLabel(pos, llvm::AtomicOrdering::Release, addr, size, AType::Signed, - SVal(0), deps) - {} - - DEFINE_CREATE_CLONE(UnlockWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_UnlockWrite; } -}; - -/******************************************************************************* - ** BInitWriteLabel Class - ******************************************************************************/ - -/* Specialization of writes for barrier initializations */ -class BInitWriteLabel : public WriteLabel { - -public: - BInitWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, const EventDeps &deps = EventDeps()) - : WriteLabel(EL_BInitWrite, pos, ord, addr, size, type, val, deps) - {} - - DEFINE_CREATE_CLONE(BInitWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_BInitWrite; } -}; - -/******************************************************************************* - ** BDestroyWriteLabel Class - ******************************************************************************/ - -/* Specialization of writes for barrier destruction */ -class BDestroyWriteLabel : public WriteLabel { - -public: - BDestroyWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, const EventDeps &deps = EventDeps()) - : WriteLabel(EL_BDestroyWrite, pos, ord, addr, size, type, val, deps) - {} - - DEFINE_CREATE_CLONE(BDestroyWriteLabel) +#define WRITE_PURE_SUBCLASS(_class_kind) \ + class _class_kind##Label : public WriteLabel { \ + \ + public: \ + _class_kind##Label(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ + AType type, SVal val, WriteAttr wattr, \ + const EventDeps &deps = EventDeps()) \ + : WriteLabel(_class_kind, pos, ord, loc, size, type, val, wattr, deps) \ + {} \ + _class_kind##Label(Event pos, llvm::AtomicOrdering ord, SAddr loc, ASize size, \ + AType type, SVal val, const EventDeps &deps = EventDeps()) \ + : _class_kind \ + ##Label(pos, ord, loc, size, type, val, WriteAttr::None, deps) \ + {} \ + \ + DEFINE_STANDARD_MEMBERS(_class_kind) \ + }; - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_BDestroyWrite; } -}; +WRITE_PURE_SUBCLASS(UnlockWrite); +WRITE_PURE_SUBCLASS(BInitWrite); +WRITE_PURE_SUBCLASS(BDestroyWrite); +WRITE_PURE_SUBCLASS(CondVarInitWrite); +WRITE_PURE_SUBCLASS(CondVarSignalWrite); +WRITE_PURE_SUBCLASS(CondVarBcastWrite); +WRITE_PURE_SUBCLASS(CondVarDestroyWrite); /******************************************************************************* ** FaiWriteLabel Class @@ -1391,19 +1218,22 @@ class FaiWriteLabel : public WriteLabel { public: FaiWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr, const EventDeps &deps = EventDeps()) - : FaiWriteLabel(EL_FaiWrite, pos, ord, addr, size, type, val, wattr, deps) + : FaiWriteLabel(FaiWrite, pos, ord, addr, size, type, val, wattr, deps) {} FaiWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, const EventDeps &deps = EventDeps()) : FaiWriteLabel(pos, ord, addr, size, type, val, WriteAttr::None, deps) {} - DEFINE_CREATE_CLONE(FaiWriteLabel) + DEFINE_CREATE_CLONE(FaiWrite) static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } static bool classofKind(EventLabelKind k) { - return k >= EL_FaiWrite && k <= EL_FaiWriteLast; + return +#define FIRST_FAI_WRITE_LABEL(NUM) k >= NUM && +#define LAST_FAI_WRITE_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" } }; @@ -1418,13 +1248,10 @@ class NoRetFaiWriteLabel : public FaiWriteLabel { NoRetFaiWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr = WriteAttr::None, const EventDeps &deps = EventDeps()) - : FaiWriteLabel(EL_NoRetFaiWrite, pos, ord, addr, size, type, val, wattr, deps) + : FaiWriteLabel(NoRetFaiWrite, pos, ord, addr, size, type, val, wattr, deps) {} - DEFINE_CREATE_CLONE(NoRetFaiWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_NoRetFaiWrite; } + DEFINE_STANDARD_MEMBERS(NoRetFaiWrite) }; /******************************************************************************* @@ -1437,18 +1264,15 @@ class BIncFaiWriteLabel : public FaiWriteLabel { public: BIncFaiWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr, const EventDeps &deps = EventDeps()) - : FaiWriteLabel(EL_BIncFaiWrite, pos, ord, addr, size, type, val, wattr, deps) + : FaiWriteLabel(BIncFaiWrite, pos, ord, addr, size, type, val, wattr, deps) {} BIncFaiWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, const EventDeps &deps = EventDeps()) - : FaiWriteLabel(EL_BIncFaiWrite, pos, ord, addr, size, type, val, WriteAttr::None, + : FaiWriteLabel(BIncFaiWrite, pos, ord, addr, size, type, val, WriteAttr::None, deps) {} - DEFINE_CREATE_CLONE(BIncFaiWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_BIncFaiWrite; } + DEFINE_STANDARD_MEMBERS(BIncFaiWrite) }; /******************************************************************************* @@ -1469,41 +1293,36 @@ class CasWriteLabel : public WriteLabel { CasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr = WriteAttr::None, const EventDeps &deps = EventDeps()) - : CasWriteLabel(EL_CasWrite, pos, ord, addr, size, type, val, wattr, deps) + : CasWriteLabel(CasWrite, pos, ord, addr, size, type, val, wattr, deps) {} - DEFINE_CREATE_CLONE(CasWriteLabel) + DEFINE_CREATE_CLONE(CasWrite) static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } static bool classofKind(EventLabelKind k) { - return k >= EL_CasWrite && k <= EL_CasWriteLast; + return +#define FIRST_CAS_WRITE_LABEL(NUM) k >= NUM && +#define LAST_CAS_WRITE_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" } }; #define CASWRITE_PURE_SUBCLASS(_class_kind) \ - class _class_kind##CasWriteLabel : public CasWriteLabel { \ + class _class_kind##Label : public CasWriteLabel { \ \ public: \ - _class_kind##CasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, \ - ASize size, AType type, SVal val, \ - WriteAttr wattr = WriteAttr::None, \ - const EventDeps &deps = EventDeps()) \ - : CasWriteLabel(EL_##_class_kind##CasWrite, pos, ord, addr, size, type, \ - val, wattr, deps) \ + _class_kind##Label(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, \ + AType type, SVal val, WriteAttr wattr = WriteAttr::None, \ + const EventDeps &deps = EventDeps()) \ + : CasWriteLabel(_class_kind, pos, ord, addr, size, type, val, wattr, deps) \ {} \ \ - DEFINE_CREATE_CLONE(_class_kind##CasWriteLabel) \ - \ - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } \ - static bool classofKind(EventLabelKind k) \ - { \ - return k == EL_##_class_kind##CasWrite; \ - } \ + DEFINE_STANDARD_MEMBERS(_class_kind) \ }; -CASWRITE_PURE_SUBCLASS(Helped); -CASWRITE_PURE_SUBCLASS(Confirming); +CASWRITE_PURE_SUBCLASS(HelpedCasWrite); +CASWRITE_PURE_SUBCLASS(ConfirmingCasWrite); /******************************************************************************* ** LockCasWriteLabel Class @@ -1515,7 +1334,7 @@ class LockCasWriteLabel : public CasWriteLabel { public: LockCasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr, const EventDeps &deps = EventDeps()) - : CasWriteLabel(EL_LockCasWrite, pos, ord, addr, size, type, val, wattr, deps) + : CasWriteLabel(LockCasWrite, pos, ord, addr, size, type, val, wattr, deps) {} LockCasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, const EventDeps &deps = EventDeps()) @@ -1526,10 +1345,7 @@ class LockCasWriteLabel : public CasWriteLabel { SVal(1), deps) {} - DEFINE_CREATE_CLONE(LockCasWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_LockCasWrite; } + DEFINE_STANDARD_MEMBERS(LockCasWrite) }; /******************************************************************************* @@ -1543,8 +1359,8 @@ class TrylockCasWriteLabel : public CasWriteLabel { TrylockCasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, WriteAttr wattr, const EventDeps &deps = EventDeps()) - : CasWriteLabel(EL_TrylockCasWrite, pos, ord, addr, size, type, val, - WriteAttr::None, deps) + : CasWriteLabel(TrylockCasWrite, pos, ord, addr, size, type, val, WriteAttr::None, + deps) {} TrylockCasWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal val, const EventDeps &deps = EventDeps()) @@ -1555,187 +1371,7 @@ class TrylockCasWriteLabel : public CasWriteLabel { AType::Signed, SVal(1), deps) {} - DEFINE_CREATE_CLONE(TrylockCasWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_TrylockCasWrite; } -}; - -/******************************************************************************* - ** DskWriteLabel Class - ******************************************************************************/ - -/* Models a write to disk (e.g., via write()) */ -class DskWriteLabel : public WriteLabel, public DskAccessLabel { - -protected: - DskWriteLabel(EventLabelKind k, Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, - AType type, SVal val, void *mapping, const EventDeps &deps = EventDeps()) - : WriteLabel(k, pos, ord, addr, size, type, val, deps), DskAccessLabel(k), - mapping(mapping) - {} - -public: - DskWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, void *mapping, const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskWrite, pos, ord, addr, size, type, val, mapping, deps) - {} - - DskWriteLabel(Event pos, SAddr addr, ASize size, AType type, SVal val, void *mapping, - const EventDeps &deps = EventDeps()) - : DskWriteLabel(pos, llvm::AtomicOrdering::Release, addr, size, type, val, mapping, - deps) - {} - - /* Returns the starting offset for this write's disk mapping */ - const void *getMapping() const { return mapping; } - - DEFINE_CREATE_CLONE(DskWriteLabel) - - virtual void reset() override - { - WriteLabel::reset(); - DskAccessLabel::reset(); - } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) - { - return k >= EL_DskWrite && k <= EL_LastDskWrite; - } - static DskAccessLabel *castToDskAccessLabel(const DskWriteLabel *D) - { - return static_cast(const_cast(D)); - } - static DskWriteLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } - -private: - /* The starting offset for this write's disk mapping */ - void *mapping; -}; - -/******************************************************************************* - ** DskMdWriteLabel Class - ******************************************************************************/ - -/* Models a disk write that writes metadata */ -class DskMdWriteLabel : public DskWriteLabel { - -public: - DskMdWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, void *mapping, std::pair ordDataRange, - const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskMdWrite, pos, ord, addr, size, type, val, mapping, deps), - ordDataRange(ordDataRange) - {} - - DskMdWriteLabel(Event pos, SAddr addr, ASize size, AType type, SVal val, void *mapping, - std::pair ordDataRange, const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskMdWrite, pos, llvm::AtomicOrdering::Release, addr, size, type, - val, mapping, deps), - ordDataRange(ordDataRange) - {} - - /* Helpers that return data with which this write is ordered */ - const void *getOrdDataBegin() const { return ordDataRange.first; } - const void *getOrdDataEnd() const { return ordDataRange.second; } - const std::pair getOrdDataRange() const { return ordDataRange; } - - DEFINE_CREATE_CLONE(DskMdWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskMdWrite; } - static DskAccessLabel *castToDskAccessLabel(const DskMdWriteLabel *D) - { - return static_cast(const_cast(D)); - } - static DskMdWriteLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } - -private: - /* The data range [begin, end) that with which this write is ordered */ - std::pair ordDataRange; -}; - -/******************************************************************************* - ** DskDirWriteLabel Class - ******************************************************************************/ - -/* Models a write to a directory on disk */ -class DskDirWriteLabel : public DskWriteLabel { - -public: - DskDirWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, void *mapping, const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskDirWrite, pos, ord, addr, size, type, val, mapping, deps) - {} - - DskDirWriteLabel(Event pos, SAddr addr, ASize size, AType type, SVal val, void *mapping, - const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskDirWrite, pos, llvm::AtomicOrdering::Release, addr, size, - type, val, mapping, deps) - {} - - DEFINE_CREATE_CLONE(DskDirWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskDirWrite; } - static DskAccessLabel *castToDskAccessLabel(const DskDirWriteLabel *D) - { - return static_cast(const_cast(D)); - } - static DskDirWriteLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } -}; - -/******************************************************************************* - ** DskJnlWriteLabel Class - ******************************************************************************/ - -/* Models a write to disk that marks the beginning or end of a disk transaction. - * (We assume that each transaction affects only one inode.) */ -class DskJnlWriteLabel : public DskWriteLabel { - -public: - DskJnlWriteLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, - SVal val, void *mapping, void *inode, const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskJnlWrite, pos, ord, addr, size, type, val, mapping, deps), - inode(inode) - {} - - DskJnlWriteLabel(Event pos, SAddr addr, ASize size, AType type, SVal val, void *mapping, - void *inode, const EventDeps &deps = EventDeps()) - : DskWriteLabel(EL_DskJnlWrite, pos, llvm::AtomicOrdering::Release, addr, size, - type, val, mapping, deps), - inode(inode) - {} - - /* Returns the inode on which the transaction takes place */ - const void *getTransInode() const { return inode; } - - DEFINE_CREATE_CLONE(DskJnlWriteLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskJnlWrite; } - static DskAccessLabel *castToDskAccessLabel(const DskJnlWriteLabel *D) - { - return static_cast(const_cast(D)); - } - static DskJnlWriteLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } - -private: - /* The inode on which the transaction takes place */ - void *inode; + DEFINE_STANDARD_MEMBERS(TrylockCasWrite) }; /******************************************************************************* @@ -1752,399 +1388,26 @@ class FenceLabel : public EventLabel { {} public: - FenceLabel(Event pos, llvm::AtomicOrdering ord, const EventDeps &deps = EventDeps()) - : FenceLabel(EL_Fence, pos, ord, deps) - {} - - DEFINE_CREATE_CLONE(FenceLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_Fence && k <= EL_LastFence; } -}; - -/******************************************************************************* - ** DskFsyncLabel Class - ******************************************************************************/ - -/* Represents an fsync() operation */ -class DskFsyncLabel : public FenceLabel, public DskAccessLabel { - -public: - DskFsyncLabel(Event pos, llvm::AtomicOrdering ord, const void *inode, unsigned int size, - const EventDeps &deps = EventDeps()) - : FenceLabel(EL_DskFsync, pos, ord, deps), DskAccessLabel(EL_DskFsync), - inode(inode), size(size) - {} - DskFsyncLabel(Event pos, const void *inode, unsigned int size, - const EventDeps &deps = EventDeps()) - : DskFsyncLabel(pos, llvm::AtomicOrdering::Release, inode, size, deps) - {} - - /* Returns a pointer to the inode on which the fsync() took place */ - const void *getInode() const { return inode; } - - /* Returns the "size" of this fsync()'s range */ - unsigned int getSize() const { return size; } - - DEFINE_CREATE_CLONE(DskFsyncLabel) - - virtual void reset() override - { - FenceLabel::reset(); - DskAccessLabel::reset(); - } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskFsync; } - static DskAccessLabel *castToDskAccessLabel(const DskFsyncLabel *D) - { - return static_cast(const_cast(D)); - } - static DskFsyncLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } - -private: - /* The inode on which the fsync() was issued */ - const void *inode; - - /* The range of this fsync() */ - const unsigned int size; -}; - -/******************************************************************************* - ** DskSyncLabel Class - ******************************************************************************/ - -/* Represents an operation that synchronizes writes to persistent storage (e.g, sync()) */ -class DskSyncLabel : public FenceLabel, public DskAccessLabel { - -public: - DskSyncLabel(Event pos, llvm::AtomicOrdering ord, const EventDeps &deps = EventDeps()) - : FenceLabel(EL_DskSync, pos, ord, deps), DskAccessLabel(EL_DskSync) - {} - DskSyncLabel(Event pos, const EventDeps &deps = EventDeps()) - : DskSyncLabel(pos, llvm::AtomicOrdering::Release, deps) - {} - - DEFINE_CREATE_CLONE(DskSyncLabel) - - virtual void reset() override - { - FenceLabel::reset(); - DskAccessLabel::reset(); - } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskSync; } - static DskAccessLabel *castToDskAccessLabel(const DskSyncLabel *D) - { - return static_cast(const_cast(D)); - } - static DskSyncLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } -}; - -/****************************************************************************** - ** DskPbarrierLabel Class - ******************************************************************************/ - -/* Corresponds to a call to __VERIFIER_pbarrier(), i.e., - * all events before this label will have persisted when the - * recovery routine runs */ -class DskPbarrierLabel : public FenceLabel, public DskAccessLabel { - -public: - DskPbarrierLabel(Event pos, llvm::AtomicOrdering ord, const EventDeps &deps = EventDeps()) - : FenceLabel(EL_DskPbarrier, pos, ord, deps), DskAccessLabel(EL_DskPbarrier) - {} - - DskPbarrierLabel(Event pos, const EventDeps &deps = EventDeps()) - : DskPbarrierLabel(pos, llvm::AtomicOrdering::Release, deps) - {} - - DEFINE_CREATE_CLONE(DskPbarrierLabel) - - virtual void reset() override - { - FenceLabel::reset(); - DskAccessLabel::reset(); - } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskPbarrier; } - static DskAccessLabel *castToDskAccessLabel(const DskPbarrierLabel *D) - { - return static_cast(const_cast(D)); - } - static DskPbarrierLabel *castFromDskAccessLabel(const DskAccessLabel *DC) - { - return static_cast(const_cast(DC)); - } -}; - -/******************************************************************************* - ** SmpFenceKLMMLabel Class - ******************************************************************************/ - -enum class SmpFenceType { MB = 0, WMB, RMB, MBBA, MBAA, MBAS, MBAUL }; -inline bool isCumul(SmpFenceType t) { return t <= SmpFenceType::WMB || t >= SmpFenceType::MBBA; } -inline bool isStrong(SmpFenceType t) { return t == SmpFenceType::MB || t >= SmpFenceType::MBBA; } - -/* Represents a non-C11-type fence (LKMM only) */ -class SmpFenceLabelLKMM : public FenceLabel { - -public: - SmpFenceLabelLKMM(Event pos, llvm::AtomicOrdering ord, SmpFenceType t, - const EventDeps &deps = EventDeps()) - : FenceLabel(EL_SmpFenceLKMM, pos, - ::isStrong(t) ? llvm::AtomicOrdering::SequentiallyConsistent - : llvm::AtomicOrdering::Monotonic, - deps), - type(t) - {} - - static bool isType(const EventLabel *lab, SmpFenceType type) - { - if (auto *fLab = llvm::dyn_cast(lab)) - return fLab->getType() == type; - return false; - } - - /* Returns the type of this fence */ - SmpFenceType getType() const { return type; } - - /* Returns true if this fence is cumulative */ - bool isCumul() const { return ::isCumul(getType()); } - - /* Returns true if this fence is a strong fence */ - bool isStrong() const { return ::isStrong(getType()); } - - DEFINE_CREATE_CLONE(SmpFenceLabelLKMM) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_SmpFenceLKMM; } - -private: - /* The type of this LKMM fence */ - SmpFenceType type; -}; - -/****************************************************************************** - ** RCUSyncLabelLKMM Class - ******************************************************************************/ - -/* Corresponds to a the beginning of a grace period */ -class RCUSyncLabelLKMM : public FenceLabel { - -public: - RCUSyncLabelLKMM(Event pos, const EventDeps &deps = EventDeps()) - : FenceLabel(EL_RCUSyncLKMM, pos, llvm::AtomicOrdering::SequentiallyConsistent, - deps) - {} - - DEFINE_CREATE_CLONE(RCUSyncLabelLKMM) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_RCUSyncLKMM; } - -private: - /* The discriminator suffices */ -}; - -/******************************************************************************* - ** ThreadCreateLabel Class - ******************************************************************************/ - -/* This label denotes the creation of a thread (via, e.g., pthread_create()) */ -class ThreadCreateLabel : public EventLabel { - -public: - ThreadCreateLabel(Event pos, llvm::AtomicOrdering ord, ThreadInfo childInfo, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_ThreadCreate, pos, ord, deps), childInfo(childInfo) - {} - ThreadCreateLabel(Event pos, ThreadInfo childInfo, const EventDeps &deps = EventDeps()) - : ThreadCreateLabel(pos, llvm::AtomicOrdering::Release, childInfo, deps) - {} - - /* Getters for the created thread's info */ - const ThreadInfo &getChildInfo() const { return childInfo; } - ThreadInfo &getChildInfo() { return childInfo; } - - /* Getter/setter for the identifier of the created thread */ - unsigned int getChildId() const { return getChildInfo().id; } - void setChildId(unsigned int tid) { getChildInfo().id = tid; } - - DEFINE_CREATE_CLONE(ThreadCreateLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_ThreadCreate; } - -private: - /* Information about the child thread */ - ThreadInfo childInfo; -}; - -/******************************************************************************* - ** ThreadJoinLabel Class - ******************************************************************************/ - -/* Represents a join() operation (e.g., pthread_join()) */ -class ThreadJoinLabel : public EventLabel { - -public: - ThreadJoinLabel(Event pos, llvm::AtomicOrdering ord, unsigned int childId, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_ThreadJoin, pos, ord, deps), childId(childId) - {} - ThreadJoinLabel(Event pos, unsigned int childId, const EventDeps &deps = EventDeps()) - : ThreadJoinLabel(pos, llvm::AtomicOrdering::Acquire, childId, deps) - {} - - /* Returns the identifier of the thread this join() is waiting on */ - unsigned int getChildId() const { return childId; } - - DEFINE_CREATE_CLONE(ThreadJoinLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_ThreadJoin; } - -private: - /* The identifier of the child */ - const unsigned int childId; -}; - -/******************************************************************************* - ** ThreadKillLabel Class - ******************************************************************************/ - -/* Represents the abnormal termination of a thread */ -class ThreadKillLabel : public EventLabel { - -public: - ThreadKillLabel(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_ThreadKill, pos, llvm::AtomicOrdering::NotAtomic, deps) - {} - - DEFINE_CREATE_CLONE(ThreadKillLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_ThreadKill; } -}; - -/******************************************************************************* - ** ThreadStartLabel Class - ******************************************************************************/ - -/* Represents the beginning of a thread. This label synchronizes with the - * ThreadCreateLabel that led to the creation of this thread */ -class ThreadStartLabel : public EventLabel { - -protected: - ThreadStartLabel(EventLabelKind kind, Event pos, Event pc) - : EventLabel(kind, pos, llvm::AtomicOrdering::Acquire, EventDeps()), - parentCreate(pc), threadInfo() - {} - -public: - ThreadStartLabel(Event pos, llvm::AtomicOrdering ord, Event pc, ThreadInfo tinfo, - int symm = -1) - : EventLabel(EL_ThreadStart, pos, ord, EventDeps()), parentCreate(pc), - threadInfo(tinfo), symmetricTid(symm) - {} - ThreadStartLabel(Event pos, Event pc, ThreadInfo tinfo, int symm = -1) - : ThreadStartLabel(pos, llvm::AtomicOrdering::Acquire, pc, tinfo, symm) - {} - - /* Returns the position of the corresponding create operation */ - Event getParentCreate() const { return parentCreate; } - - /* Getters for the thread's info */ - const ThreadInfo &getThreadInfo() const { return threadInfo; } - ThreadInfo &getThreadInfo() { return threadInfo; } - - /* SR: Returns the id of a symmetric thread, or -1 if no symmetric thread exists */ - int getSymmetricTid() const { return symmetricTid; } - - DEFINE_CREATE_CLONE(ThreadStartLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) - { - return k >= EL_ThreadStart && k <= EL_ThreadStartEnd; - } - -private: - /* The position of the corresponding create opeartion */ - Event parentCreate; - - /* Information about this thread */ - ThreadInfo threadInfo; - - /* SR: The tid a symmetric thread (currently: minimum among all) */ - int symmetricTid = -1; -}; - -/******************************************************************************* - ** ThreadFinishLabel Class - ******************************************************************************/ - -/* Represents the ending of a thread. This label synchronizes with the - * ThreadJoinLabel that awaits for this particular thread (if any) - * - * FIXME: no error is reported if multiple threads are waiting on the - * same thread */ -class ThreadFinishLabel : public EventLabel { - -public: - ThreadFinishLabel(Event pos, llvm::AtomicOrdering ord, SVal retVal) - : EventLabel(EL_ThreadFinish, pos, ord, EventDeps()), retVal(retVal) - {} - - ThreadFinishLabel(Event pos, SVal retVal) - : ThreadFinishLabel(pos, llvm::AtomicOrdering::Release, retVal) - {} - - /* Returns the join() operation waiting on this thread or - NULL if no such operation exists (yet) */ - ThreadJoinLabel *getParentJoin() const { return parentJoin; } - - /* Sets the corresponding join() event */ - void setParentJoin(ThreadJoinLabel *jLab) { parentJoin = jLab; } - - /* Returns the return value of this thread */ - SVal getRetVal() const { return retVal; } + FenceLabel(Event pos, llvm::AtomicOrdering ord, const EventDeps &deps = EventDeps()) + : FenceLabel(Fence, pos, ord, deps) + {} - DEFINE_CREATE_CLONE(ThreadFinishLabel) + DEFINE_CREATE_CLONE(Fence) - virtual void reset() override + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } + static bool classofKind(EventLabelKind k) { - EventLabel::reset(); - parentJoin = nullptr; + return +#define FIRST_FENCE_LABEL(NUM) k >= NUM && +#define LAST_FENCE_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" } - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_ThreadFinish; } - -private: - /* Position of corresponding join() event in the graph - * (NULL if such event does not exist) */ - ThreadJoinLabel *parentJoin = nullptr; - - /* Return value of the thread */ - SVal retVal; }; /******************************************************************************* ** MallocLabel Class ******************************************************************************/ -class FreeLabel; - /* Corresponds to a memory-allocating operation (e.g., malloc()) */ class MallocLabel : public EventLabel { @@ -2153,7 +1416,7 @@ class MallocLabel : public EventLabel { unsigned alignment, StorageDuration sd, StorageType stype, AddressSpace spc, const NameInfo *info, const std::string &name, const EventDeps &deps = EventDeps()) - : EventLabel(EL_Malloc, pos, ord, deps), allocAddr(addr), allocSize(size), + : EventLabel(Malloc, pos, ord, deps), allocAddr(addr), allocSize(size), alignment(alignment), sdur(sd), stype(stype), spc(spc), nameInfo(info), name(name) {} MallocLabel(Event pos, SAddr addr, unsigned int size, unsigned alignment, @@ -2173,8 +1436,6 @@ class MallocLabel : public EventLabel { : MallocLabel(pos, size, alignment, sd, stype, spc, nullptr, {}, deps) {} - DEFINE_CREATE_CLONE(MallocLabel) - /* Getter/setter for the (fresh) address returned by the allocation */ SAddr getAllocAddr() const { return allocAddr; } void setAllocAddr(SAddr addr) { allocAddr = addr; } @@ -2236,8 +1497,16 @@ class MallocLabel : public EventLabel { accessList.clear(); } + DEFINE_CREATE_CLONE(Malloc) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_Malloc; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_ALLOC_LABEL(NUM) k >= NUM && +#define LAST_ALLOC_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: friend class ExecutionGraph; @@ -2271,10 +1540,10 @@ class MallocLabel : public EventLabel { AccessList accessList; /* The size of the requested allocation */ - unsigned int allocSize; + unsigned int allocSize{}; /* Allocation alignment */ - unsigned int alignment; + unsigned int alignment{}; /* Storage duration */ StorageDuration sdur; @@ -2289,7 +1558,7 @@ class MallocLabel : public EventLabel { std::string name; /* Naming information for this allocation */ - const NameInfo *nameInfo; + const NameInfo *nameInfo{}; }; /******************************************************************************* @@ -2312,7 +1581,7 @@ class FreeLabel : public EventLabel { public: FreeLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, unsigned int size, const EventDeps &deps = EventDeps()) - : FreeLabel(EL_Free, pos, ord, addr, size, deps) + : FreeLabel(Free, pos, ord, addr, size, deps) {} FreeLabel(Event pos, SAddr addr, unsigned int size, const EventDeps &deps = EventDeps()) : FreeLabel(pos, llvm::AtomicOrdering::NotAtomic, addr, size, deps) @@ -2339,26 +1608,32 @@ class FreeLabel : public EventLabel { return getFreedAddr() <= addr && addr < getFreedAddr() + getFreedSize(); } - DEFINE_CREATE_CLONE(FreeLabel) - virtual void reset() override { EventLabel::reset(); aLab = nullptr; } + DEFINE_CREATE_CLONE(Free) + static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k >= EL_Free && k <= EL_FreeLast; } + static bool classofKind(EventLabelKind k) + { + return +#define FIRST_FREE_LABEL(NUM) k >= NUM && +#define LAST_FREE_LABEL(NUM) k <= NUM; +#include "ExecutionGraph/EventLabel.def" + } private: /* The address of the memory freed */ SAddr freeAddr; /* The size of the memory freed */ - unsigned int freedSize; + unsigned int freedSize{}; /* The corresponding allocation */ - MallocLabel *aLab = nullptr; + MallocLabel *aLab{}; }; /******************************************************************************* @@ -2371,7 +1646,7 @@ class HpRetireLabel : public FreeLabel { public: HpRetireLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, unsigned int size, const EventDeps &deps = EventDeps()) - : FreeLabel(EL_HpRetire, pos, ord, addr, size, deps) + : FreeLabel(HpRetire, pos, ord, addr, size, deps) {} HpRetireLabel(Event pos, SAddr addr, unsigned int size, const EventDeps &deps = EventDeps()) : HpRetireLabel(pos, llvm::AtomicOrdering::NotAtomic, addr, size, deps) @@ -2380,101 +1655,94 @@ class HpRetireLabel : public FreeLabel { : HpRetireLabel(pos, addr, 0, deps) {} - DEFINE_CREATE_CLONE(HpRetireLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_HpRetire; } + DEFINE_STANDARD_MEMBERS(HpRetire) }; /******************************************************************************* - ** HpProtectLabel Class + ** ThreadCreateLabel Class ******************************************************************************/ -/* Specialization of writes for hazptr protect events */ -class HpProtectLabel : public EventLabel { +/* This label denotes the creation of a thread (via, e.g., pthread_create()) */ +class ThreadCreateLabel : public EventLabel { public: - HpProtectLabel(Event pos, llvm::AtomicOrdering ord, SAddr hpAddr, SAddr protAddr, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_HpProtect, pos, ord, deps), hpAddr(hpAddr), protAddr(protAddr) + ThreadCreateLabel(Event pos, llvm::AtomicOrdering ord, ThreadInfo childInfo, + const EventDeps &deps = EventDeps()) + : EventLabel(ThreadCreate, pos, ord, deps), childInfo(childInfo) {} - HpProtectLabel(Event pos, SAddr hpAddr, SAddr protAddr, const EventDeps &deps = EventDeps()) - : HpProtectLabel(pos, llvm::AtomicOrdering::Release, hpAddr, protAddr, deps) + ThreadCreateLabel(Event pos, ThreadInfo childInfo, const EventDeps &deps = EventDeps()) + : ThreadCreateLabel(pos, llvm::AtomicOrdering::Release, childInfo, deps) {} - /* Getters for HP/protected address */ - SAddr getHpAddr() const { return hpAddr; } - SAddr getProtectedAddr() const { return protAddr; } + /* Getters for the created thread's info */ + const ThreadInfo &getChildInfo() const { return childInfo; } + ThreadInfo &getChildInfo() { return childInfo; } - DEFINE_CREATE_CLONE(HpProtectLabel) + /* Getter/setter for the identifier of the created thread */ + unsigned int getChildId() const { return getChildInfo().id; } + void setChildId(unsigned int tid) { getChildInfo().id = tid; } - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_HpProtect; } + DEFINE_STANDARD_MEMBERS(ThreadCreate) private: - /* HP address */ - SAddr hpAddr; - - /* Protected address */ - SAddr protAddr; + /* Information about the child thread */ + ThreadInfo childInfo; }; /******************************************************************************* - ** LockLabelLAPOR Class + ** ThreadJoinLabel Class ******************************************************************************/ -/* Corresponds to a label modeling a lock operation --under LAPOR only-- */ -class LockLabelLAPOR : public EventLabel { +/* Represents a join() operation (e.g., pthread_join()) */ +class ThreadJoinLabel : public EventLabel { public: - LockLabelLAPOR(Event pos, llvm::AtomicOrdering ord, SAddr addr, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_LockLAPOR, pos, ord, deps), lockAddr(addr) + ThreadJoinLabel(Event pos, llvm::AtomicOrdering ord, unsigned int childId, + const EventDeps &deps = EventDeps()) + : EventLabel(ThreadJoin, pos, ord, deps), childId(childId) {} - LockLabelLAPOR(Event pos, SAddr addr, const EventDeps &deps = EventDeps()) - : LockLabelLAPOR(pos, llvm::AtomicOrdering::Acquire, addr, deps) + ThreadJoinLabel(Event pos, unsigned int childId, const EventDeps &deps = EventDeps()) + : ThreadJoinLabel(pos, llvm::AtomicOrdering::Acquire, childId, deps) {} - /* Returns the address of the acquired lock */ - SAddr getLockAddr() const { return lockAddr; } - - DEFINE_CREATE_CLONE(LockLabelLAPOR) + /* Returns the identifier of the thread this join() is waiting on */ + unsigned int getChildId() const { return childId; } - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_LockLAPOR; } + DEFINE_STANDARD_MEMBERS(ThreadJoin) private: - /* The address of the acquired lock */ - SAddr lockAddr; + /* The identifier of the child */ + const unsigned int childId{}; }; /******************************************************************************* - ** UnlockLabelLAPOR Class + ** HpProtectLabel Class ******************************************************************************/ -/* Corresponds to a label modeling an unlock operation --under LAPOR only-- */ -class UnlockLabelLAPOR : public EventLabel { +/* Specialization of writes for hazptr protect events */ +class HpProtectLabel : public EventLabel { public: - UnlockLabelLAPOR(Event pos, llvm::AtomicOrdering ord, SAddr addr, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_UnlockLAPOR, pos, ord, deps), lockAddr(addr) + HpProtectLabel(Event pos, llvm::AtomicOrdering ord, SAddr hpAddr, SAddr protAddr, + const EventDeps &deps = EventDeps()) + : EventLabel(HpProtect, pos, ord, deps), hpAddr(hpAddr), protAddr(protAddr) {} - UnlockLabelLAPOR(Event pos, SAddr addr, const EventDeps &deps = EventDeps()) - : UnlockLabelLAPOR(pos, llvm::AtomicOrdering::Release, addr, deps) + HpProtectLabel(Event pos, SAddr hpAddr, SAddr protAddr, const EventDeps &deps = EventDeps()) + : HpProtectLabel(pos, llvm::AtomicOrdering::Release, hpAddr, protAddr, deps) {} - /* Returns the address of the released lock */ - SAddr getLockAddr() const { return lockAddr; } - - DEFINE_CREATE_CLONE(UnlockLabelLAPOR) + /* Getters for HP/protected address */ + SAddr getHpAddr() const { return hpAddr; } + SAddr getProtectedAddr() const { return protAddr; } - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_UnlockLAPOR; } + DEFINE_STANDARD_MEMBERS(HpProtect) private: - /* The address of the released lock */ - SAddr lockAddr; + /* HP address */ + SAddr hpAddr; + + /* Protected address */ + SAddr protAddr; }; /******************************************************************************* @@ -2487,7 +1755,7 @@ class HelpingCasLabel : public EventLabel { public: HelpingCasLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, ASize size, AType type, SVal exp, SVal swap, const EventDeps &deps = EventDeps()) - : EventLabel(EL_HelpingCas, pos, ord, deps), access(AAccess(addr, size, type)), + : EventLabel(HelpingCas, pos, ord, deps), access(AAccess(addr, size, type)), expected(exp), swapValue(swap) {} @@ -2509,10 +1777,7 @@ class HelpingCasLabel : public EventLabel { /* Returns the value that the supposed CAS writes */ SVal getSwapVal() const { return swapValue; } - DEFINE_CREATE_CLONE(HelpingCasLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_HelpingCas; } + DEFINE_STANDARD_MEMBERS(HelpingCas) private: /* The size of the access performed (in bytes) */ @@ -2525,323 +1790,94 @@ class HelpingCasLabel : public EventLabel { const SVal swapValue; }; -/****************************************************************************** - ** DskOpenLabel Class - ******************************************************************************/ - -/* Corresponds to the beginning of a file-opening operation (e.g., open()) */ -class DskOpenLabel : public EventLabel { - -public: - DskOpenLabel(Event pos, llvm::AtomicOrdering ord, const std::string &fileName, SVal fd, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_DskOpen, pos, ord, deps), fileName(fileName), fd(fd) - {} - DskOpenLabel(Event pos, const std::string &fileName, SVal fd = SVal(0), - const EventDeps &deps = EventDeps()) - : DskOpenLabel(pos, llvm::AtomicOrdering::Release, fileName, fd, deps) - {} - - /* Returns the name of the opened file */ - const std::string &getFileName() const { return fileName; } - - /* Setter/getter for the file descriptor returned by open() */ - SVal getFd() const { return fd; } - void setFd(SVal d) { fd = d; } - - DEFINE_CREATE_CLONE(DskOpenLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_DskOpen; } - -private: - /* The name of the opened file */ - std::string fileName; - - /* The file descriptor allocated for this call */ - SVal fd; -}; - -/****************************************************************************** - ** RCULockLabelLKMM Class - ******************************************************************************/ - -/* Corresponds to the beginning of an RCU read-side critical section */ -class RCULockLabelLKMM : public EventLabel { - -public: - RCULockLabelLKMM(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_RCULockLKMM, pos, llvm::AtomicOrdering::Acquire, deps) - {} - - DEFINE_CREATE_CLONE(RCULockLabelLKMM) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_RCULockLKMM; } -}; - -/****************************************************************************** - ** RCUUnlockLabelLKMM Class - ******************************************************************************/ - -/* Corresponds to the ending of an RCU read-side critical section */ -class RCUUnlockLabelLKMM : public EventLabel { - -public: - RCUUnlockLabelLKMM(Event pos, const EventDeps &deps = EventDeps()) - : EventLabel(EL_RCUUnlockLKMM, pos, llvm::AtomicOrdering::Release, deps) - {} - - DEFINE_CREATE_CLONE(RCUUnlockLabelLKMM) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_RCUUnlockLKMM; } -}; - /******************************************************************************* - ** CLFlushLabel Class + ** OptionalLabel Class ******************************************************************************/ -/* Represents a cache line flush */ -class CLFlushLabel : public EventLabel { +/* A label that represents the beginning of an optional block */ +class OptionalLabel : public EventLabel { public: - CLFlushLabel(Event pos, llvm::AtomicOrdering ord, SAddr addr, - const EventDeps &deps = EventDeps()) - : EventLabel(EL_CLFlush, pos, ord, deps), addr(addr) - {} - CLFlushLabel(Event pos, SAddr addr, const EventDeps &deps = EventDeps()) - : CLFlushLabel(pos, llvm::AtomicOrdering::Monotonic, addr, deps) + OptionalLabel(Event pos, const EventDeps &deps = EventDeps()) + : EventLabel(Optional, pos, llvm::AtomicOrdering::NotAtomic, deps) {} - /* Returns a pointer to the addr on which the flush takes place */ - SAddr getAddr() const { return addr; } + /* Whether this block is expandable */ + bool isExpandable() const { return expandable; } + void setExpandable(bool exp) { expandable = exp; } - DEFINE_CREATE_CLONE(CLFlushLabel) + /* Whether this block has been expanded */ + bool isExpanded() const { return expanded; } + void setExpanded(bool exp) { expanded = exp; } - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_CLFlush; } + DEFINE_STANDARD_MEMBERS(Optional) private: - SAddr addr; + bool expandable = true; + bool expanded = false; }; /******************************************************************************* - ** InitLabel Class + ** Dummy subclasses ******************************************************************************/ -/* Represents the INIT label of the graph, modeling the initialization of all - * memory locaitons. The first thread is special in that it does not start with - * a ThreadStartLabel as the other threads do */ -class InitLabel : public ThreadStartLabel { - -private: - using ReaderList = CopyableIList; - friend class ExecutionGraph; - friend class DepExecutionGraph; - -public: - InitLabel() : ThreadStartLabel(EL_Init, Event::getInit(), Event::getInit()) {} - - using rf_iterator = ReaderList::iterator; - using const_rf_iterator = ReaderList::const_iterator; - - rf_iterator rf_begin(SAddr addr) { return initRfs[addr].begin(); } - const_rf_iterator rf_begin(SAddr addr) const { return initRfs.at(addr).begin(); }; - rf_iterator rf_end(SAddr addr) { return initRfs[addr].end(); } - const_rf_iterator rf_end(SAddr addr) const { return initRfs.at(addr).end(); } - - DEFINE_CREATE_CLONE(InitLabel) - - static bool classof(const EventLabel *lab) { return classofKind(lab->getKind()); } - static bool classofKind(EventLabelKind k) { return k == EL_Init; } - -private: - void addReader(ReadLabel *rLab) - { - BUG_ON(std::find_if(rf_begin(rLab->getAddr()), rf_end(rLab->getAddr()), - [rLab](ReadLabel &oLab) { - return oLab.getPos() == rLab->getPos(); - }) != rf_end(rLab->getAddr())); - initRfs[rLab->getAddr()].push_back(*rLab); - } +#define DEFINE_DUMMY_SUBCLASS(_class_kind) \ + class _class_kind##Label : public EventLabel { \ + public: \ + _class_kind##Label(Event pos, const EventDeps &deps = EventDeps()) \ + : EventLabel(_class_kind, pos, llvm::AtomicOrdering::NotAtomic, deps) \ + {} \ + \ + DEFINE_STANDARD_MEMBERS(_class_kind) \ + }; - /* Removes all readers that satisfy predicate F */ - template void removeReader(SAddr addr, F cond) - { - for (auto it = rf_begin(addr); it != rf_end(addr);) { - if (cond(*it)) - it = initRfs[addr].erase(it); - else - ++it; - } - } +DEFINE_DUMMY_SUBCLASS(LoopBegin) +DEFINE_DUMMY_SUBCLASS(SpinStart) +DEFINE_DUMMY_SUBCLASS(FaiZNESpinEnd) +DEFINE_DUMMY_SUBCLASS(LockZNESpinEnd) +DEFINE_DUMMY_SUBCLASS(Empty) - std::unordered_map initRfs; -}; +/******************************************************************************* + ** Out-of-class definitions + *******************************************************************************/ -inline bool EventLabel::isStable() const +inline void InitLabel::addReader(ReadLabel *rLab) { - auto *mLab = llvm::dyn_cast(this); - return !isRevisitable() || (mLab && !mLab->wasAddedMax()); + BUG_ON(std::find_if(rf_begin(rLab->getAddr()), rf_end(rLab->getAddr()), + [rLab](ReadLabel &oLab) { return oLab.getPos() == rLab->getPos(); }) != + rf_end(rLab->getAddr())); + initRfs[rLab->getAddr()].push_back(*rLab); } /******************************************************************************* ** Static methods *******************************************************************************/ -inline EventLabel *EventLabel::castFromDskAccessLabel(const DskAccessLabel *D) +inline bool EventLabel::isStable() const { - EventLabel::EventLabelKind DK = D->getEventLabelKind(); - switch (DK) { - case EventLabel::EventLabelKind::EL_DskRead: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskWrite: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskMdWrite: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskJnlWrite: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskDirWrite: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskSync: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskFsync: - return static_cast(const_cast(D)); - case EventLabel::EventLabelKind::EL_DskPbarrier: - return static_cast(const_cast(D)); - default: - BUG(); - } + auto *mLab = llvm::dyn_cast(this); + return !isRevisitable() || (mLab && !mLab->wasAddedMax()); } -inline DskAccessLabel *EventLabel::castToDskAccessLabel(const EventLabel *E) +inline bool EventLabel::isDependable(EventLabelKind k) { - EventLabel::EventLabelKind EK = E->getKind(); - switch (EK) { - case EventLabel::EventLabelKind::EL_DskRead: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskWrite: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskMdWrite: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskJnlWrite: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskDirWrite: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskSync: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskFsync: - return static_cast(const_cast(E)); - case EventLabel::EventLabelKind::EL_DskPbarrier: - return static_cast(const_cast(E)); - default: - BUG(); - } + return ReadLabel::classofKind(k) || k == Malloc || k == Optional; } -/******************************************************************************* - ** RTTI helpers - *******************************************************************************/ - -/* Specialization selected when ToTy is not a known subclass of DskAccessLabel */ -template ::value> -struct cast_convert_decl_context { - static const ToTy *doit(const DskAccessLabel *Val) - { - return static_cast(EventLabel::castFromDskAccessLabel(Val)); - } - - static ToTy *doit(DskAccessLabel *Val) - { - return static_cast(EventLabel::castFromDskAccessLabel(Val)); - } -}; - -/* Specialization selected when ToTy is a known subclass of DskAccessLabel */ -template struct cast_convert_decl_context { - static const ToTy *doit(const DskAccessLabel *Val) - { - return static_cast(Val); - } - - static ToTy *doit(DskAccessLabel *Val) { return static_cast(Val); } -}; - -namespace llvm { - -/* isa(DskAccessLabel *) */ -template struct isa_impl { - static bool doit(const ::DskAccessLabel &Val) - { - return To::classofKind(Val.getEventLabelKind()); - } -}; - -/* cast(DskAccessLabel *) */ -template -struct cast_convert_val { - static const ToTy &doit(const ::DskAccessLabel &Val) - { - return *::cast_convert_decl_context::doit(&Val); - } -}; - -template struct cast_convert_val { - static ToTy &doit(::DskAccessLabel &Val) - { - return *::cast_convert_decl_context::doit(&Val); - } -}; - -template -struct cast_convert_val { - static const ToTy *doit(const ::DskAccessLabel *Val) - { - return ::cast_convert_decl_context::doit(Val); - } -}; - -template struct cast_convert_val { - static ToTy *doit(::DskAccessLabel *Val) - { - return ::cast_convert_decl_context::doit(Val); - } -}; - -/// Implement cast_convert_val for EventLabel -> DskAccessLabel conversions. -template struct cast_convert_val<::DskAccessLabel, FromTy, FromTy> { - static ::DskAccessLabel &doit(const FromTy &Val) - { - return *FromTy::castToDskAccessLabel(&Val); - } -}; - -template struct cast_convert_val<::DskAccessLabel, FromTy *, FromTy *> { - static ::DskAccessLabel *doit(const FromTy *Val) - { - return FromTy::castToDskAccessLabel(Val); - } -}; - -template struct cast_convert_val { - static const ::DskAccessLabel &doit(const FromTy &Val) - { - return *FromTy::castToDskAccessLabel(&Val); - } -}; +inline bool EventLabel::hasValue(EventLabelKind k) +{ + return ThreadStartLabel::classofKind(k) || ReadLabel::classofKind(k) || k == ThreadJoin || + k == Optional; +} -template struct cast_convert_val { - static const ::DskAccessLabel *doit(const FromTy *Val) - { - return FromTy::castToDskAccessLabel(Val); - } -}; +inline bool EventLabel::hasLocation(EventLabelKind k) { return MemAccessLabel::classofKind(k); } -} /* namespace llvm */ +inline bool ReadLabel::isConfirming(EventLabelKind k) +{ + return ConfirmingReadLabel::classofKind(k) || ConfirmingCasReadLabel::classofKind(k); +} llvm::raw_ostream &operator<<(llvm::raw_ostream &rhs, const llvm::AtomicOrdering o); llvm::raw_ostream &operator<<(llvm::raw_ostream &rhs, const EventLabel::EventLabelKind k); -llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const SmpFenceType t); -#endif /* __EVENTLABEL_HPP__ */ +#endif /* GENMC_EVENTLABEL_HPP */ diff --git a/src/ExecutionGraph.cpp b/src/ExecutionGraph/ExecutionGraph.cpp similarity index 94% rename from src/ExecutionGraph.cpp rename to src/ExecutionGraph/ExecutionGraph.cpp index 17a8adc..8bdbaa4 100644 --- a/src/ExecutionGraph.cpp +++ b/src/ExecutionGraph/ExecutionGraph.cpp @@ -19,9 +19,8 @@ */ #include "ExecutionGraph.hpp" -#include "GraphIterators.hpp" -#include "Parser.hpp" -#include "config.h" +#include "ExecutionGraph/GraphIterators.hpp" +#include "Support/Parser.hpp" #include /************************************************************ @@ -71,8 +70,7 @@ Event ExecutionGraph::getLastThreadReleaseAtLoc(Event upperLimit, SAddr addr) co { for (int i = upperLimit.index - 1; i > 0; i--) { const EventLabel *lab = getEventLabel(Event(upperLimit.thread, i)); - if (llvm::isa(lab) || llvm::isa(lab) || - llvm::isa(lab)) { + if (llvm::isa(lab) || llvm::isa(lab)) { return Event(upperLimit.thread, i); } if (auto *fLab = llvm::dyn_cast(lab)) { @@ -167,12 +165,13 @@ Event ExecutionGraph::getMatchingSpeculativeRead(Event conf, Event *sc /* = null Event ExecutionGraph::getMalloc(const SAddr &addr) const { - auto it = std::find_if(label_begin(*this), label_end(*this), [&](auto &lab) { + auto range = labels(); + auto it = std::ranges::find_if(range, [&](auto &lab) { if (auto *aLab = llvm::dyn_cast(&lab)) return aLab->contains(addr); return false; }); - return it != label_end(*this) ? it->getPos() : Event::getInit(); + return it != std::ranges::end(range) ? it->getPos() : Event::getInit(); } Event ExecutionGraph::getMallocCounterpart(const FreeLabel *fLab) const @@ -259,7 +258,7 @@ std::vector ExecutionGraph::getInitRfsAtLoc(SAddr addr) const { std::vector result; - for (const auto &lab : labels(*this)) { + for (const auto &lab : labels()) { if (auto *rLab = llvm::dyn_cast(&lab)) if (rLab->getRf() && rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) @@ -274,18 +273,26 @@ std::vector ExecutionGraph::getInitRfsAtLoc(SAddr addr) const EventLabel *ExecutionGraph::addLabelToGraph(std::unique_ptr lab) { + lab->setParent(this); + /* Assign stamp if necessary */ if (!lab->hasStamp()) lab->setStamp(nextStamp()); + /* Track coherence if necessary */ + if (auto *mLab = llvm::dyn_cast(&*lab)) + trackCoherenceAtLoc(mLab->getAddr()); + auto pos = lab->getPos(); if (pos.index < events[pos.thread].size()) { auto eLab = getEventLabel(pos); BUG_ON(eLab && !llvm::isa(eLab)); + insertionOrder.remove(*events[pos.thread][pos.index]); events[pos.thread][pos.index] = std::move(lab); } else { events[pos.thread].push_back(std::move(lab)); } + insertionOrder.push_back(*events[pos.thread][pos.index]); BUG_ON(pos.index > events[pos.thread].size()); return getEventLabel(pos); } @@ -336,12 +343,13 @@ void ExecutionGraph::removeLast(unsigned int thread) dLab->setAlloc(nullptr); } /* Nothing to do for create/join: childId remains the same */ + insertionOrder.remove(*lab); resizeThread(lab->getPos()); } bool ExecutionGraph::isStoreReadByExclusiveRead(Event store, SAddr ptr) const { - for (const auto &lab : labels(*this)) { + for (const auto &lab : labels()) { if (!isRMWLoad(&lab)) continue; @@ -355,7 +363,7 @@ bool ExecutionGraph::isStoreReadByExclusiveRead(Event store, SAddr ptr) const bool ExecutionGraph::isStoreReadBySettledRMW(Event store, SAddr ptr, const VectorClock &prefix) const { - for (const auto &lab : labels(*this)) { + for (const auto &lab : labels()) { if (!isRMWLoad(&lab)) continue; @@ -485,6 +493,9 @@ void ExecutionGraph::cutToStamp(Stamp stamp) /* Inform all calculators about the events cutted */ removeAfter(*preds); + for (auto labIt = insertionOrder.begin(), labE = insertionOrder.end(); labIt != labE;) { + labIt = preds->contains(labIt->getPos()) ? ++labIt : insertionOrder.erase(labIt); + } /* Remove any 'pointers' to events that will be removed */ for (auto i = 0u; i < preds->size(); i++) { @@ -536,7 +547,7 @@ void ExecutionGraph::cutToStamp(Stamp stamp) void ExecutionGraph::compressStampsAfter(Stamp st) { resetStamp(st + 1); - for (auto &lab : labels(*this)) { + for (auto &lab : labels()) { if (lab.getStamp() > st) lab.setStamp(nextStamp()); } @@ -575,7 +586,16 @@ void ExecutionGraph::copyGraphUpTo(ExecutionGraph &other, const VectorClock &v) } } - for (auto &lab : labels(other)) { + other.insertionOrder.clear(); + for (auto &lab : insertionOrder) { + if (v.contains(lab.getPos())) { + other.insertionOrder.push_back(*other.getEventLabel(lab.getPos())); + } else if (lab.getIndex() <= v.getMax(lab.getThread())) { + other.insertionOrder.push_back(*other.getEventLabel(lab.getPos())); + } + } + + for (auto &lab : other.labels()) { auto *rLab = llvm::dyn_cast(&lab); if (rLab && rLab->getRf()) { if (!other.containsPos(rLab->getRf()->getPos())) @@ -640,19 +660,11 @@ void ExecutionGraph::copyGraphUpTo(ExecutionGraph &other, const VectorClock &v) } /* Finally, copy coherence info */ - /* FIXME: Temporary ugly hack */ - // for (auto it = cc->begin(); it != cc->end(); ++it) { - // for (auto sIt = it->second.begin(); sIt != it->second.end(); ++sIt) { - // if (v.contains(*sIt)) { - // occ->addStoreToLoc(it->first, *sIt, -1); - // } - // } - // } for (auto lIt = loc_begin(), lE = loc_end(); lIt != lE; ++lIt) { for (auto sIt = lIt->second.begin(); sIt != lIt->second.end(); ++sIt) if (v.contains(sIt->getPos())) { - other.addStoreToCO(other.getWriteLabel(sIt->getPos()), - other.co_end(lIt->first)); + other.addStoreToCOAfter(other.getWriteLabel(sIt->getPos()), + other.co_max(sIt->getAddr())); } } for (auto it = loc_begin(); it != loc_end(); ++it) { @@ -664,7 +676,6 @@ void ExecutionGraph::copyGraphUpTo(ExecutionGraph &other, const VectorClock &v) } } } - /* FIXME: Make sure all fields are copied */ return; } @@ -702,7 +713,7 @@ bool ExecutionGraph::isRMWLoad(const EventLabel *lab) const void ExecutionGraph::validate(void) { - for (auto &lab : labels(*this)) { + for (auto &lab : labels()) { if (auto *rLab = llvm::dyn_cast(&lab)) { if (!rLab->getRf()) continue; diff --git a/src/ExecutionGraph.hpp b/src/ExecutionGraph/ExecutionGraph.hpp similarity index 83% rename from src/ExecutionGraph.hpp rename to src/ExecutionGraph/ExecutionGraph.hpp index 9fa2e61..bfa9aa0 100644 --- a/src/ExecutionGraph.hpp +++ b/src/ExecutionGraph/ExecutionGraph.hpp @@ -18,21 +18,22 @@ * Author: Michalis Kokologiannakis */ -#ifndef __EXECUTION_GRAPH_HPP__ -#define __EXECUTION_GRAPH_HPP__ - -#include "AdjList.hpp" -#include "DepInfo.hpp" -#include "Error.hpp" -#include "Event.hpp" -#include "EventLabel.hpp" -#include "Revisit.hpp" -#include "Stamp.hpp" -#include "VectorClock.hpp" +#ifndef GENMC_EXECUTION_GRAPH_HPP +#define GENMC_EXECUTION_GRAPH_HPP + +#include "ADT/AdjList.hpp" +#include "ADT/VectorClock.hpp" +#include "ExecutionGraph/DepInfo.hpp" +#include "ExecutionGraph/Event.hpp" +#include "ExecutionGraph/EventLabel.hpp" +#include "ExecutionGraph/Stamp.hpp" +#include "Support/Error.hpp" +#include "Verification/Revisit.hpp" #include "config.h" #include #include +#include #include class PSCCalculator; @@ -75,6 +76,9 @@ class ExecutionGraph { using loc_iterator = LocMap::iterator; using const_loc_iterator = LocMap::const_iterator; + using label_iterator = llvm::simple_ilist::iterator; + using const_label_iterator = llvm::simple_ilist::const_iterator; + using co_iterator = StoreList::iterator; using const_co_iterator = StoreList::const_iterator; using reverse_co_iterator = StoreList::reverse_iterator; @@ -93,6 +97,70 @@ class ExecutionGraph { const_reverse_iterator rbegin() const { return events.rbegin(); }; const_reverse_iterator rend() const { return events.rend(); }; + auto label_begin() const { return insertionOrder.begin(); } + auto label_end() const { return insertionOrder.end(); } + auto labels() const { return std::views::all(insertionOrder); } + + auto label_begin() { return insertionOrder.begin(); } + auto label_end() { return insertionOrder.end(); } + auto labels() { return std::views::all(insertionOrder); } + + auto thr_ids() const { return std::views::iota(0, (int)getNumThreads()); } + auto thr_ids() { return std::views::iota(0, (int)getNumThreads()); } + + auto po_succs(const EventLabel *lab) const + { + const auto &thr = events[lab->getThread()]; + return std::ranges::subrange(thr.begin() + lab->getIndex() + 1, thr.end()) | + std::ranges::views::transform(indirect); + } + auto po_succs(EventLabel *lab) + { + auto &thr = events[lab->getThread()]; + return std::ranges::subrange(thr.begin() + lab->getIndex() + 1, thr.end()) | + std::ranges::views::transform(indirect); + } + + auto po_preds(const EventLabel *lab) const + { + const auto &thr = events[lab->getThread()]; + return std::ranges::subrange(thr.begin(), thr.begin() + lab->getIndex()) | + std::views::reverse | std::ranges::views::transform(indirect); + } + auto po_preds(EventLabel *lab) + { + const auto &thr = events[lab->getThread()]; + return std::ranges::subrange(thr.begin(), thr.begin() + lab->getIndex()) | + std::views::reverse | std::ranges::views::transform(indirect); + } + + /* Returns the label in the previous position of E. + * Returns nullptr if E is the first event of a thread */ + const EventLabel *getPreviousLabel(const EventLabel *lab) const + { + return lab->getIndex() == 0 ? nullptr + : events[lab->getThread()][lab->getIndex() - 1].get(); + } + EventLabel *getPreviousLabel(EventLabel *lab) + { + return const_cast( + static_cast(*this).getPreviousLabel(lab)); + } + + /* Returns the label in the next position of E. + * Returns nullptr if E is the last event of a thread */ + const EventLabel *getNextLabel(const EventLabel *lab) const + { + return lab->getIndex() == getThreadSize(lab->getThread()) - 1 + ? nullptr + : events[lab->getThread()][lab->getIndex() + 1].get(); + } + EventLabel *getNextLabel(EventLabel *lab) + { + return const_cast( + static_cast(*this).getNextLabel(lab)); + } + loc_iterator loc_begin() { return coherence.begin(); } const_loc_iterator loc_begin() const { return coherence.begin(); }; loc_iterator loc_end() { return coherence.end(); } @@ -102,6 +170,8 @@ class ExecutionGraph { const_co_iterator co_begin(SAddr addr) const { return coherence.at(addr).begin(); }; co_iterator co_end(SAddr addr) { return coherence[addr].end(); } const_co_iterator co_end(SAddr addr) const { return coherence.at(addr).end(); } + auto co(SAddr addr) { return std::views::all(coherence[addr]); } + auto co(SAddr addr) const { return std::views::all(coherence.at(addr)); } reverse_co_iterator co_rbegin(SAddr addr) { return coherence[addr].rbegin(); } const_reverse_co_iterator co_rbegin(SAddr addr) const @@ -110,6 +180,11 @@ class ExecutionGraph { }; reverse_co_iterator co_rend(SAddr addr) { return coherence[addr].rend(); } const_reverse_co_iterator co_rend(SAddr addr) const { return coherence.at(addr).rend(); } + auto rco(SAddr addr) { return std::views::all(coherence[addr]) | std::views::reverse; } + auto rco(SAddr addr) const + { + return std::views::all(coherence.at(addr)) | std::views::reverse; + } initrf_iterator init_rf_begin(SAddr addr) { return getInitLabel()->rf_begin(addr); } const_initrf_iterator init_rf_begin(SAddr addr) const @@ -156,6 +231,17 @@ class ExecutionGraph { static_cast(*this).co_imm_pred(lab)); } + const EventLabel *co_max(SAddr addr) const + { + return co_begin(addr) == co_end(addr) ? (EventLabel *)getInitLabel() + : (EventLabel *)&*co_rbegin(addr); + } + EventLabel *co_max(SAddr addr) + { + return const_cast( + static_cast(*this).co_max(addr)); + } + co_iterator fr_succ_begin(ReadLabel *rLab) { auto *wLab = llvm::dyn_cast(rLab->getRf()); @@ -260,12 +346,31 @@ class ExecutionGraph { * (Maintains well-formedness for read removals.) */ EventLabel *addLabelToGraph(std::unique_ptr lab); - void addStoreToCO(WriteLabel *wLab, co_iterator it) + void addStoreToCOBefore(WriteLabel *wLab, WriteLabel *succLab) + { + coherence[wLab->getAddr()].insert(co_iterator(succLab), *wLab); + } + void addStoreToCOAfter(WriteLabel *wLab, EventLabel *predLab) { - coherence[wLab->getAddr()].insert(it, *wLab); + auto *predLabW = llvm::dyn_cast(predLab); + coherence[wLab->getAddr()].insert( + predLabW ? ++co_iterator(*predLabW) : co_begin(wLab->getAddr()), *wLab); } + void removeStoreFromCO(WriteLabel *wLab) { coherence[wLab->getAddr()].remove(*wLab); } + void moveStoreCOBefore(WriteLabel *wLab, WriteLabel *succLab) + { + removeStoreFromCO(wLab); + addStoreToCOBefore(wLab, succLab); + } + + void moveStoreCOAfter(WriteLabel *wLab, EventLabel *predLab) + { + removeStoreFromCO(wLab); + addStoreToCOAfter(wLab, predLab); + } + /* Removes the last event from THREAD. * If it is a read, updates the rf-lists. * If it is a write, makes all readers read BOT. */ @@ -305,40 +410,6 @@ class ExecutionGraph { static_cast(*this).getWriteLabel(e)); } - /* Returns the label in the previous position of E. - * Returns nullptr if E is the first event of a thread */ - const EventLabel *getPreviousLabel(Event e) const - { - return e.index == 0 ? nullptr : getEventLabel(e.prev()); - } - EventLabel *getPreviousLabel(Event e) - { - return const_cast( - static_cast(*this).getPreviousLabel(e)); - } - const EventLabel *getPreviousLabel(const EventLabel *lab) const - { - return getPreviousLabel(lab->getPos()); - } - EventLabel *getPreviousLabel(EventLabel *lab) { return getPreviousLabel(lab->getPos()); } - - /* Returns the label in the next position of E. - * Returns nullptr if E is the last event of a thread */ - const EventLabel *getNextLabel(Event e) const - { - return e == getLastThreadEvent(e.thread) ? nullptr : getEventLabel(e.next()); - } - EventLabel *getNextLabel(Event e) - { - return const_cast( - static_cast(*this).getNextLabel(e)); - } - const EventLabel *getNextLabel(const EventLabel *lab) const - { - return getNextLabel(lab->getPos()); - } - EventLabel *getNextLabel(EventLabel *lab) { return getNextLabel(lab->getPos()); } - /* Returns the previous non-empty label of e. Since all threads * have an initializing event, it returns that as a base case */ const EventLabel *getPreviousNonEmptyLabel(Event e) const; @@ -487,13 +558,6 @@ class ExecutionGraph { return isRMWStore(sLab) && !getPendingRMW(sLab).isInitializer(); } - /* Helper: Returns true if RLAB is a confirming operation */ - bool isConfirming(const ReadLabel *rLab) const - { - return llvm::isa(rLab) || - llvm::isa(rLab); - } - /* Returns true if store is read a successful RMW in the location ptr */ bool isStoreReadByExclusiveRead(Event store, SAddr addr) const; @@ -550,6 +614,11 @@ class ExecutionGraph { friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const ExecutionGraph &g); protected: + static auto indirect(const std::unique_ptr &ptr) -> EventLabel & + { + return *ptr; + } + void resizeThread(unsigned int tid, unsigned int size) { events[tid].resize(size); }; void resizeThread(Event pos) { resizeThread(pos.thread, pos.index); } @@ -597,10 +666,12 @@ class ExecutionGraph { LocMap coherence; + llvm::simple_ilist insertionOrder; + /* Pers: The ID of the recovery routine. * It should be -1 if not in recovery mode, or have the * value of the recovery routine otherwise. */ int recoveryTID = -1; }; -#endif /* __EXECUTION_GRAPH_HPP__ */ +#endif /* GENMC_EXECUTION_GRAPH_HPP */ diff --git a/src/GraphIterators.hpp b/src/ExecutionGraph/GraphIterators.hpp similarity index 53% rename from src/GraphIterators.hpp rename to src/ExecutionGraph/GraphIterators.hpp index c8e7ce3..eae3d81 100644 --- a/src/GraphIterators.hpp +++ b/src/ExecutionGraph/GraphIterators.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __GRAPH_ITERATORS_HPP__ -#define __GRAPH_ITERATORS_HPP__ +#ifndef GENMC_GRAPH_ITERATORS_HPP +#define GENMC_GRAPH_ITERATORS_HPP #include "ExecutionGraph.hpp" #include "config.h" @@ -32,261 +32,25 @@ * Helper iterators for ExecutionGraphs */ -/******************************************************************************* - ** LabelIterator Class - ******************************************************************************/ - -/* - * This class implements some helper iterators for ExecutionGraph. - * A bit ugly, but easily tunable, and deals with UP containers - */ -template -class LabelIterator { - -protected: - ThreadT *threads; - ThreadItT thread; - LabelItT label; - -public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = LabelT; - using difference_type = signed; - using pointer = LabelT *; - using reference = LabelT &; /* ugly hack to avoid having UP refs */ - - using BaseT = LabelIterator; - - /*** Constructor ***/ - LabelIterator() = default; - - /* begin()/end() constructor */ - template < - typename G, typename U = ThreadItT, - std::enable_if_t>, bool> = true, - std::enable_if_t().begin())>::value> - * = nullptr> - LabelIterator(G &g) : threads(&g.getThreadList()), thread(g.begin()) - { - if (thread != threads->end()) { - label = thread->begin(); - advanceThread(); - } - } - template ().begin())>::value> * = nullptr> - LabelIterator(G &g, bool) : threads(&g.getThreadList()), thread(g.end()) - {} - - /* rbegin()/rend() constructor */ - template >, bool> = true, - typename std::enable_if_t().rbegin())>::value> * = nullptr> - LabelIterator(G &g) : threads(&g.getThreadList()), thread(g.rbegin()) - { - if (thread != threads->rend()) { - label = thread->rbegin(); - advanceThread(); - } - } - template ().rbegin())>::value> * = nullptr> - LabelIterator(G &g, bool) : threads(&g.getThreadList()), thread(g.rend()) - {} - - /* iterator-from-label constructor (normal iterator) */ - template ().begin())>::value> * = nullptr> - LabelIterator(G &g, pointer p) - : threads(&g.getThreadList()), thread(g.begin() + p->getThread()), - label(thread->begin() + p->getIndex()) - {} - - template ().begin())>::value> * = nullptr> - LabelIterator(G &g, Event e) - : threads(&g.getThreadList()), thread(g.begin() + e.thread), - label(thread->begin() + e.index) - { - advanceThread(); - } - - /* iterator-from-label constructor (reverse iterator) */ - template ().rbegin())>::value> * = nullptr> - LabelIterator(G &g, pointer p) - : threads(&g.getThreadList()), - thread(g.rbegin() + threads->size() - p->getThread() - 1), - label(thread->rbegin() + g.getThreadSize(p->getThread()) - p->getIndex() - 1) - {} - - template ().rbegin())>::value> * = nullptr> - LabelIterator(G &g, Event e) - : threads(&g.getThreadList()), - thread(g.rbegin() + g.getThreadList().size() - e.thread - 1), - label(thread->rbegin() + g.getThreadSize(e.thread) - e.index - 1) - { - advanceThread(); - } - - /*** Operators ***/ - inline reference operator*() const { return **label; } - inline pointer operator->() const { return &operator*(); } - - template ().begin())>::value> * = nullptr> - inline bool operator==(const LabelIterator &other) const - { - return thread == other.thread && (thread == threads->end() || label == other.label); - } - - template ().rbegin())>::value> * = nullptr> - inline bool operator==(const LabelIterator &other) const - { - return thread == other.thread && - (thread == threads->rend() || label == other.label); - } - - inline bool operator!=(const LabelIterator &other) const { return !operator==(other); } - - LabelIterator &operator++() - { - ++label; - advanceThread(); - return *this; - } - inline LabelIterator operator++(int) - { - auto tmp = *this; - ++*this; - return tmp; - } - - LabelIterator &operator--() - { - while (thread == threads->end() || label == thread->begin()) { - --thread; - label = thread->end(); - } - --label; - return *this; - } - inline LabelIterator operator--(int) - { - auto tmp = *this; - --*this; - return tmp; - } - -protected: - /* Checks whether we have reached the end of a thread, and appropriately - * advances the thread and label iterators. Does nothing if that is not the case. */ - template ().begin())>::value> * = nullptr> - inline void advanceThread() - { - while (label == thread->end()) { - ++thread; - if (thread == threads->end()) - break; - label = thread->begin(); - } - } - - template ().rbegin())>::value> * = nullptr> - inline void advanceThread() - { - while (label == thread->rend()) { - ++thread; - if (thread == threads->rend()) - break; - label = thread->rbegin(); - } - } -}; - -using label_iterator = LabelIterator; -using const_label_iterator = - LabelIterator; - -using reverse_label_iterator = - LabelIterator; -using const_reverse_label_iterator = - LabelIterator; +using label_iterator = ExecutionGraph::label_iterator; +using const_label_iterator = ExecutionGraph::const_label_iterator; /******************************************************************************* ** label-iteration utilities ******************************************************************************/ -using label_range = llvm::iterator_range; -using const_label_range = llvm::iterator_range; - -inline label_iterator label_begin(ExecutionGraph &G) { return label_iterator(G); } -inline const_label_iterator label_begin(const ExecutionGraph &G) { return const_label_iterator(G); } +using label_range = llvm::iterator_range; +using const_label_range = llvm::iterator_range; -inline label_iterator label_end(ExecutionGraph &G) { return label_iterator(G, true); } -inline const_label_iterator label_end(const ExecutionGraph &G) +inline auto other_labels(ExecutionGraph &G, const EventLabel *lab) { - return const_label_iterator(G, true); + return G.labels() | + std::views::filter([lab](auto &olab) { return olab.getPos() != lab->getPos(); }); } - -inline label_range labels(ExecutionGraph &G) { return label_range(label_begin(G), label_end(G)); } -inline const_label_range labels(const ExecutionGraph &G) +inline auto other_labels(const ExecutionGraph &G, const EventLabel *lab) { - return const_label_range(label_begin(G), label_end(G)); -} - -/******************************************************************************* - ** store-iteration utilities - ******************************************************************************/ - -using const_store_iterator = ExecutionGraph::const_co_iterator; -using const_store_range = llvm::iterator_range; -using const_reverse_store_iterator = ExecutionGraph::const_reverse_co_iterator; -using const_reverse_store_range = llvm::iterator_range; - -inline const_store_iterator store_begin(const ExecutionGraph &G, SAddr addr) -{ - return G.co_begin(addr); -} -inline const_store_iterator store_end(const ExecutionGraph &G, SAddr addr) -{ - return G.co_end(addr); -} -inline const_store_range stores(const ExecutionGraph &G, SAddr addr) -{ - return const_store_range(store_begin(G, addr), store_end(G, addr)); -} - -inline const_reverse_store_iterator store_rbegin(const ExecutionGraph &G, SAddr addr) -{ - return G.co_rbegin(addr); -} -inline const_reverse_store_iterator store_rend(const ExecutionGraph &G, SAddr addr) -{ - return G.co_rend(addr); -} -inline const_reverse_store_range rstores(const ExecutionGraph &G, SAddr addr) -{ - return const_reverse_store_range(store_rbegin(G, addr), store_rend(G, addr)); + return G.labels() | + std::views::filter([lab](auto &olab) { return olab.getPos() != lab->getPos(); }); } /******************************************************************************* @@ -299,23 +63,23 @@ using const_co_range = llvm::iterator_range; using const_reverse_co_range = llvm::iterator_range; namespace detail { -inline const_store_iterator coSentinel; +inline const_co_iterator coSentinel; inline const_reverse_co_iterator coRevSentinel; }; // namespace detail -inline const_store_iterator co_succ_begin(const ExecutionGraph &G, const EventLabel *lab) +inline auto co_succ_begin(const ExecutionGraph &G, const EventLabel *lab) { auto *wLab = llvm::dyn_cast(lab); return wLab ? G.co_succ_begin(wLab) : ::detail::coSentinel; } -inline const_store_iterator co_succ_end(const ExecutionGraph &G, const EventLabel *lab) +inline auto co_succ_end(const ExecutionGraph &G, const EventLabel *lab) { auto *wLab = llvm::dyn_cast(lab); return wLab ? G.co_succ_end(wLab) : ::detail::coSentinel; } -inline const_store_range co_succs(const ExecutionGraph &G, const EventLabel *lab) +inline auto co_succs(const ExecutionGraph &G, const EventLabel *lab) { - return const_store_range(co_succ_begin(G, lab), co_succ_end(G, lab)); + return const_co_range(co_succ_begin(G, lab), co_succ_end(G, lab)); } inline const WriteLabel *co_imm_succ(const ExecutionGraph &G, const EventLabel *lab) { @@ -347,60 +111,22 @@ inline const WriteLabel *co_imm_pred(const ExecutionGraph &G, const EventLabel * ** po-iteration utilities ******************************************************************************/ -using const_po_iterator = const_label_iterator; -using const_reverse_po_iterator = const_reverse_label_iterator; - -using const_po_range = llvm::iterator_range; -using const_reverse_po_range = llvm::iterator_range; - -inline const_po_iterator po_succ_begin(const ExecutionGraph &G, Event e) -{ - return const_po_iterator(G, e.next()); -} - -inline const_po_iterator po_succ_end(const ExecutionGraph &G, Event e) -{ - return e == G.getLastThreadEvent(e.thread) - ? po_succ_begin(G, e) - : const_po_iterator(G, G.getLastThreadEvent(e.thread).next()); -} +using const_po_iterator = decltype(std::declval() + .po_succs(std::declval()) + .begin()); +using const_reverse_po_iterator = decltype(std::declval() + .po_preds(std::declval()) + .begin()); -inline const_po_range po_succs(const ExecutionGraph &G, Event e) -{ - return const_po_range(po_succ_begin(G, e), po_succ_end(G, e)); -} - -inline const_po_range po_succs(const ExecutionGraph &G, const EventLabel *lab) -{ - return po_succs(G, lab->getPos()); -} +inline auto po_succs(const ExecutionGraph &G, const EventLabel *lab) { return G.po_succs(lab); } inline const EventLabel *po_imm_succ(const ExecutionGraph &G, const EventLabel *lab) { return G.getNextLabel(lab); } -inline const_reverse_po_iterator po_pred_begin(const ExecutionGraph &G, Event e) -{ - return const_reverse_po_iterator(G, e.prev()); -} - -inline const_reverse_po_iterator po_pred_end(const ExecutionGraph &G, Event e) -{ - return e == G.getFirstThreadEvent(e.thread) - ? po_pred_begin(G, e) - : const_reverse_po_iterator(G, G.getFirstThreadEvent(e.thread).prev()); -} - -inline const_reverse_po_range po_preds(const ExecutionGraph &G, Event e) -{ - return const_reverse_po_range(po_pred_begin(G, e), po_pred_end(G, e)); -} +inline auto po_preds(const ExecutionGraph &G, const EventLabel *lab) { return G.po_preds(lab); } -inline const_reverse_po_range po_preds(const ExecutionGraph &G, const EventLabel *lab) -{ - return po_preds(G, lab->getPos()); -} inline const EventLabel *po_imm_pred(const ExecutionGraph &G, const EventLabel *lab) { return G.getPreviousLabel(lab); @@ -477,123 +203,49 @@ struct poloc_filter_iterator : public llvm::filter_iterator(lab) || llvm::isa(lab); -} +static inline bool hasLocation(const EventLabel *lab) { return lab->hasLocation(); } static inline SAddr getLocation(const EventLabel *lab) { if (auto *mLab = llvm::dyn_cast(lab)) return mLab->getAddr(); - if (auto *fLab = llvm::dyn_cast(lab)) - return fLab->getAddr(); return SAddr(); } } /* namespace detail */ -using const_poloc_iterator = ::detail::poloc_filter_iterator; -using const_reverse_poloc_iterator = ::detail::poloc_filter_iterator; - -using const_poloc_range = llvm::iterator_range; -using const_reverse_poloc_range = llvm::iterator_range; - -inline const_poloc_iterator poloc_succ_begin(const ExecutionGraph &G, Event e) -{ - using namespace ::detail; - auto *lab = G.getEventLabel(e); - return hasLocation(lab) ? const_poloc_iterator(po_succ_begin(G, e), po_succ_end(G, e), - LocationFilter(G, getLocation(lab))) - : const_poloc_iterator(po_succ_end(G, e), po_succ_end(G, e), - LocationFilter(G, SAddr())); -} - -inline const_poloc_iterator poloc_succ_end(const ExecutionGraph &G, Event e) -{ - using namespace ::detail; - auto *lab = G.getEventLabel(e); - auto addr = hasLocation(lab) ? getLocation(lab) : SAddr(); - return const_poloc_iterator(po_succ_end(G, e), po_succ_end(G, e), LocationFilter(G, addr)); -} - -inline const_poloc_range poloc_succs(const ExecutionGraph &G, Event e) -{ - return const_poloc_range(poloc_succ_begin(G, e), poloc_succ_end(G, e)); -} - -inline const_poloc_range poloc_succs(const ExecutionGraph &G, const EventLabel *lab) -{ - return poloc_succs(G, lab->getPos()); -} - -inline const_poloc_iterator poloc_imm_succ_begin(const ExecutionGraph &G, Event e) -{ - return poloc_succ_begin(G, e); -} - -inline const_poloc_iterator poloc_imm_succ_end(const ExecutionGraph &G, Event e) -{ - return poloc_succ_begin(G, e) == poloc_succ_end(G, e) ? poloc_imm_succ_begin(G, e) - : ++poloc_imm_succ_begin(G, e); -} - -inline const_poloc_range poloc_imm_succs(const ExecutionGraph &G, Event e) -{ - return const_poloc_range(poloc_imm_succ_begin(G, e), poloc_imm_succ_end(G, e)); -} -inline const_poloc_range poloc_imm_succs(const ExecutionGraph &G, const EventLabel *lab) -{ - return poloc_imm_succs(G, lab->getPos()); -} - -inline const_reverse_poloc_iterator poloc_pred_begin(const ExecutionGraph &G, Event e) -{ - using namespace ::detail; - auto *lab = G.getEventLabel(e); - return hasLocation(lab) - ? const_reverse_poloc_iterator(po_pred_begin(G, e), po_pred_end(G, e), - LocationFilter(G, getLocation(lab))) - : const_reverse_poloc_iterator(po_pred_end(G, e), po_pred_end(G, e), - LocationFilter(G, SAddr())); -} - -inline const_reverse_poloc_iterator poloc_pred_end(const ExecutionGraph &G, Event e) -{ - using namespace ::detail; - auto *lab = G.getEventLabel(e); - auto addr = hasLocation(lab) ? getLocation(lab) : SAddr(); - return const_reverse_poloc_iterator(po_pred_end(G, e), po_pred_end(G, e), - LocationFilter(G, addr)); -} - -inline const_reverse_poloc_range poloc_preds(const ExecutionGraph &G, Event e) -{ - return const_reverse_poloc_range(poloc_pred_begin(G, e), poloc_pred_end(G, e)); -} - -inline const_reverse_poloc_range poloc_preds(const ExecutionGraph &G, const EventLabel *lab) +inline auto poloc_succs(const ExecutionGraph &G, const EventLabel *lab) { - return poloc_preds(G, lab->getPos()); + /* Capture LAB explicitly as by reference it leads to weird segfaults */ + auto locFilter = [lab](auto &oLab) { + return ::detail::hasLocation(&oLab) && + ::detail::getLocation(&oLab) == ::detail::getLocation(lab); + }; + if (::detail::hasLocation(lab)) + return po_succs(G, lab) | std::views::filter(locFilter); + return po_succs(G, G.getLastThreadLabel(lab->getThread())) | std::views::filter(locFilter); } -inline const_reverse_poloc_iterator poloc_imm_pred_begin(const ExecutionGraph &G, Event e) +inline const EventLabel *poloc_imm_succ(const ExecutionGraph &G, const EventLabel *lab) { - return poloc_pred_begin(G, e); + auto succs = poloc_succs(G, lab); + return succs.begin() == succs.end() ? nullptr : &*succs.begin(); } -inline const_reverse_poloc_iterator poloc_imm_pred_end(const ExecutionGraph &G, Event e) +inline auto poloc_preds(const ExecutionGraph &G, const EventLabel *lab) { - return poloc_pred_begin(G, e) == poloc_pred_end(G, e) ? poloc_imm_pred_begin(G, e) - : ++poloc_imm_pred_begin(G, e); + auto locFilter = [lab](auto &oLab) { + return ::detail::hasLocation(&oLab) && + ::detail::getLocation(&oLab) == ::detail::getLocation(lab); + }; + return ::detail::hasLocation(lab) ? po_preds(G, lab) | std::views::filter(locFilter) + : po_preds(G, G.getFirstThreadLabel(lab->getThread())) | + std::views::filter(locFilter); } -inline const_reverse_poloc_range poloc_imm_preds(const ExecutionGraph &G, Event e) +inline const EventLabel *poloc_imm_pred(const ExecutionGraph &G, const EventLabel *lab) { - return const_reverse_poloc_range(poloc_imm_pred_begin(G, e), poloc_imm_pred_end(G, e)); -} -inline const_reverse_poloc_range poloc_imm_preds(const ExecutionGraph &G, const EventLabel *lab) -{ - return poloc_imm_preds(G, lab->getPos()); + auto preds = poloc_preds(G, lab); + return preds.begin() == preds.end() ? nullptr : &*preds.begin(); } /******************************************************************************* @@ -631,88 +283,25 @@ struct RfInvIntFilter { const ExecutionGraph &graph; const Event write; }; - -template -struct detour_filter_iterator : public llvm::filter_iterator { -public: - using BaseT = llvm::filter_iterator; - - detour_filter_iterator(IterT it, IterT end, FilterT filter) : BaseT(it, end, filter) {} - - detour_filter_iterator &operator++() - { - return static_cast(BaseT::operator++()); - } - detour_filter_iterator operator++(int) - { - auto tmp = *this; - BaseT::operator++(); - return tmp; - } -}; } /* namespace detail */ -using const_detour_iterator = - ::detail::detour_filter_iterator; -using const_detour_range = llvm::iterator_range; - -using const_reverse_detour_iterator = - ::detail::detour_filter_iterator; -using const_reverse_detour_range = llvm::iterator_range; - -inline const_detour_iterator detour_succ_begin(const ExecutionGraph &G, Event e) +inline auto detour_succs(const ExecutionGraph &G, const EventLabel *lab) { - auto *lab = G.getWriteLabel(e); - return lab ? const_detour_iterator(poloc_succ_begin(G, e), poloc_succ_end(G, e), - ::detail::RfIntFilter(G, e)) - : const_detour_iterator(poloc_succ_end(G, e), poloc_succ_end(G, e), - ::detail::RfIntFilter(G, e)); -} - -inline const_detour_iterator detour_succ_end(const ExecutionGraph &G, Event e) -{ - auto *lab = G.getWriteLabel(e); - return const_detour_iterator(poloc_succ_end(G, e), poloc_succ_end(G, e), - ::detail::RfIntFilter(G, e)); -} - -inline const_detour_range detour_succs(const ExecutionGraph &G, Event e) -{ - return const_detour_range(detour_succ_begin(G, e), detour_succ_end(G, e)); -} - -inline const_detour_range detour_succs(const ExecutionGraph &G, const EventLabel *lab) -{ - return detour_succs(G, lab->getPos()); -} - -inline const_reverse_detour_iterator detour_pred_begin(const ExecutionGraph &G, Event e) -{ - auto *lab = G.getReadLabel(e); - return lab && lab->getRf() ? const_reverse_detour_iterator( - poloc_pred_begin(G, e), poloc_pred_end(G, e), - ::detail::RfInvIntFilter(G, lab->getRf()->getPos())) - : const_reverse_detour_iterator( - poloc_pred_end(G, e), poloc_pred_end(G, e), - ::detail::RfInvIntFilter(G, Event::getInit())); -} - -inline const_reverse_detour_iterator detour_pred_end(const ExecutionGraph &G, Event e) -{ - auto *lab = G.getReadLabel(e); - auto pos = lab && lab->getRf() ? lab->getRf()->getPos() : Event::getInit(); - return const_reverse_detour_iterator(poloc_pred_end(G, e), poloc_pred_end(G, e), - ::detail::RfInvIntFilter(G, pos)); -} - -inline const_reverse_detour_range detour_preds(const ExecutionGraph &G, Event e) -{ - return const_reverse_detour_range(detour_pred_begin(G, e), detour_pred_end(G, e)); + auto *wLab = llvm::dyn_cast(lab); + return wLab ? poloc_succs(G, lab) | + std::views::filter(::detail::RfIntFilter(G, lab->getPos())) + : poloc_succs(G, G.getLastThreadLabel(lab->getThread())) | + std::views::filter(::detail::RfIntFilter(G, lab->getPos())); } -inline const_reverse_detour_range detour_preds(const ExecutionGraph &G, const EventLabel *lab) +inline auto detour_preds(const ExecutionGraph &G, const EventLabel *lab) { - return detour_preds(G, lab->getPos()); + auto *rLab = llvm::dyn_cast(lab); + return rLab && rLab->getRf() + ? poloc_preds(G, lab) | std::views::filter(::detail::RfInvIntFilter( + G, rLab->getRf()->getPos())) + : poloc_preds(G, G.getFirstThreadLabel(lab->getThread())) | + std::views::filter(::detail::RfInvIntFilter(G, Event::getInit())); } /******************************************************************************* @@ -743,9 +332,6 @@ inline const_rf_range rf_succs(const ExecutionGraph &G, const EventLabel *lab) return const_rf_range(rf_succ_begin(G, lab), rf_succ_end(G, lab)); } -using const_rf_inv_iterator = const_label_iterator; -using const_rf_inv_range = llvm::iterator_range; - inline const EventLabel *rf_pred(const ExecutionGraph &G, const EventLabel *lab) { auto *rLab = llvm::dyn_cast(lab); @@ -807,9 +393,6 @@ inline const_rfe_range rfe_succs(const ExecutionGraph &G, const EventLabel *lab) return const_rfe_range(rfe_succ_begin(G, lab), rfe_succ_end(G, lab)); } -using const_rfe_inv_iterator = const_rf_inv_iterator; -using const_rfe_inv_range = llvm::iterator_range; - inline const EventLabel *rfe_pred(const ExecutionGraph &G, const EventLabel *lab) { auto *rLab = llvm::dyn_cast(lab); @@ -871,9 +454,6 @@ inline const_rfi_range rfi_succs(const ExecutionGraph &G, const EventLabel *lab) return const_rfi_range(rfi_succ_begin(G, lab), rfi_succ_end(G, lab)); } -using const_rfi_inv_iterator = const_rf_inv_iterator; -using const_rfi_inv_range = llvm::iterator_range; - inline const EventLabel *rfi_pred(const ExecutionGraph &G, const EventLabel *lab) { auto *rLab = llvm::dyn_cast(lab); @@ -1018,9 +598,9 @@ inline const_sameloc_iterator sameloc_begin(const ExecutionGraph &G, const Event { using namespace ::detail; return hasLocation(lab) - ? const_sameloc_iterator(label_begin(G), label_end(G), + ? const_sameloc_iterator(G.label_begin(), G.label_end(), IDAndLocFilter(G, getLocation(lab), lab->getPos())) - : const_sameloc_iterator(label_end(G), label_end(G), + : const_sameloc_iterator(G.label_end(), G.label_end(), IDAndLocFilter(G, SAddr(), lab->getPos())); } @@ -1028,7 +608,7 @@ inline const_sameloc_iterator sameloc_end(const ExecutionGraph &G, const EventLa { using namespace ::detail; auto addr = hasLocation(lab) ? getLocation(lab) : SAddr(); - return const_sameloc_iterator(label_end(G), label_end(G), + return const_sameloc_iterator(G.label_end(), G.label_end(), IDAndLocFilter(G, addr, lab->getPos())); } @@ -1087,4 +667,4 @@ inline const MallocLabel *free_pred(const ExecutionGraph &G, const EventLabel *l return (!dLab || !dLab->getAlloc()) ? nullptr : dLab->getAlloc(); } -#endif /* __GRAPH_ITERATORS_HPP__ */ +#endif /* GENMC_GRAPH_ITERATORS_HPP */ diff --git a/src/LabelVisitor.hpp b/src/ExecutionGraph/LabelVisitor.hpp similarity index 73% rename from src/LabelVisitor.hpp rename to src/ExecutionGraph/LabelVisitor.hpp index 873fc20..0d17570 100644 --- a/src/LabelVisitor.hpp +++ b/src/ExecutionGraph/LabelVisitor.hpp @@ -18,11 +18,11 @@ * Author: Michalis Kokologiannakis */ -#ifndef __LABEL_VISITOR_HPP__ -#define __LABEL_VISITOR_HPP__ +#ifndef GENMC_LABEL_VISITOR_HPP +#define GENMC_LABEL_VISITOR_HPP -#include "Error.hpp" -#include "EventLabel.hpp" +#include "ExecutionGraph/EventLabel.hpp" +#include "Support/Error.hpp" #include /******************************************************************************* @@ -36,12 +36,6 @@ template class LabelVisitor { public: - /* Gets a variadic arguments because some labels have the extension suffix */ -#define VISIT_LABEL(NAME, ...) \ - case EventLabel::EL_##NAME##__VA_ARGS__: \ - return static_cast(this)->visit##NAME##Label##__VA_ARGS__( \ - static_cast(lab)) - void visit(const EventLabel *lab) { return visit(*lab); } void visit(const std::unique_ptr &lab) { return visit(*lab); } void visit(const std::shared_ptr &lab) { return visit(*lab); } @@ -49,76 +43,11 @@ template class LabelVisitor { void visit(const EventLabel &lab) { switch (lab.getKind()) { - VISIT_LABEL(Empty); - VISIT_LABEL(JoinBlock); - VISIT_LABEL(SpinloopBlock); - VISIT_LABEL(FaiZNEBlock); - VISIT_LABEL(LockZNEBlock); - VISIT_LABEL(HelpedCASBlock); - VISIT_LABEL(ConfirmationBlock); - VISIT_LABEL(LockNotAcqBlock); - VISIT_LABEL(LockNotRelBlock); - VISIT_LABEL(BarrierBlock); - VISIT_LABEL(ErrorBlock); - VISIT_LABEL(UserBlock); - VISIT_LABEL(ReadOptBlock); - VISIT_LABEL(Optional); - VISIT_LABEL(ThreadStart); - VISIT_LABEL(Init); - VISIT_LABEL(ThreadFinish); - VISIT_LABEL(ThreadCreate); - VISIT_LABEL(ThreadJoin); - VISIT_LABEL(ThreadKill); - VISIT_LABEL(LoopBegin); - VISIT_LABEL(SpinStart); - VISIT_LABEL(FaiZNESpinEnd); - VISIT_LABEL(LockZNESpinEnd); - VISIT_LABEL(Read); - VISIT_LABEL(BWaitRead); - VISIT_LABEL(SpeculativeRead); - VISIT_LABEL(ConfirmingRead); - VISIT_LABEL(FaiRead); - VISIT_LABEL(NoRetFaiRead); - VISIT_LABEL(BIncFaiRead); - VISIT_LABEL(CasRead); - VISIT_LABEL(LockCasRead); - VISIT_LABEL(TrylockCasRead); - VISIT_LABEL(HelpedCasRead); - VISIT_LABEL(ConfirmingCasRead); - VISIT_LABEL(DskRead); - VISIT_LABEL(Write); - VISIT_LABEL(UnlockWrite); - VISIT_LABEL(BInitWrite); - VISIT_LABEL(BDestroyWrite); - VISIT_LABEL(FaiWrite); - VISIT_LABEL(NoRetFaiWrite); - VISIT_LABEL(BIncFaiWrite); - VISIT_LABEL(CasWrite); - VISIT_LABEL(LockCasWrite); - VISIT_LABEL(TrylockCasWrite); - VISIT_LABEL(HelpedCasWrite); - VISIT_LABEL(ConfirmingCasWrite); - VISIT_LABEL(DskWrite); - VISIT_LABEL(DskMdWrite); - VISIT_LABEL(DskJnlWrite); - VISIT_LABEL(DskDirWrite); - VISIT_LABEL(Fence); - VISIT_LABEL(DskFsync); - VISIT_LABEL(DskSync); - VISIT_LABEL(DskPbarrier); - VISIT_LABEL(SmpFence, LKMM); - VISIT_LABEL(RCUSync, LKMM); - VISIT_LABEL(Malloc); - VISIT_LABEL(Free); - VISIT_LABEL(HpRetire); - VISIT_LABEL(HpProtect); - VISIT_LABEL(Lock, LAPOR); - VISIT_LABEL(Unlock, LAPOR); - VISIT_LABEL(HelpingCas); - VISIT_LABEL(DskOpen); - VISIT_LABEL(RCULock, LKMM); - VISIT_LABEL(RCUUnlock, LKMM); - VISIT_LABEL(CLFlush); +#define HANDLE_LABEL(NUM, NAME) \ + case EventLabel::NAME: \ + return static_cast(this)->visit##NAME##Label( \ + static_cast(lab)); +#include "ExecutionGraph/EventLabel.def" default: BUG(); } @@ -127,10 +56,12 @@ template class LabelVisitor { #define DELEGATE_LABEL(TO_CLASS) \ static_cast(this)->visit##TO_CLASS(static_cast(lab)) - void visitEmptyLabel(const EmptyLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitOptionalLabel(const OptionalLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitThreadStartLabel(const ThreadStartLabel &lab) + { + return DELEGATE_LABEL(EventLabel); + } + void visitInitLabel(const InitLabel &lab) { return DELEGATE_LABEL(ThreadStartLabel); } - void visitJoinBlockLabel(const JoinBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); } void visitSpinloopBlockLabel(const SpinloopBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); @@ -165,59 +96,31 @@ template class LabelVisitor { } void visitErrorBlockLabel(const ErrorBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); } void visitUserBlockLabel(const UserBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); } + void visitJoinBlockLabel(const JoinBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); } void visitReadOptBlockLabel(const ReadOptBlockLabel &lab) { return DELEGATE_LABEL(BlockLabel); } - - void visitInitLabel(const InitLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitThreadStartLabel(const ThreadStartLabel &lab) - { - return DELEGATE_LABEL(EventLabel); - } - void visitThreadFinishLabel(const ThreadFinishLabel &lab) - { - return DELEGATE_LABEL(EventLabel); - } - void visitThreadCreateLabel(const ThreadCreateLabel &lab) - { - return DELEGATE_LABEL(EventLabel); - } - void visitThreadJoinLabel(const ThreadJoinLabel &lab) { return DELEGATE_LABEL(EventLabel); } void visitThreadKillLabel(const ThreadKillLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitLoopBeginLabel(const LoopBeginLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitSpinStartLabel(const SpinStartLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitFaiZNESpinEndLabel(const FaiZNESpinEndLabel &lab) - { - return DELEGATE_LABEL(EventLabel); - } - void visitLockZNESpinEndLabel(const LockZNESpinEndLabel &lab) + void visitThreadFinishLabel(const ThreadFinishLabel &lab) { return DELEGATE_LABEL(EventLabel); } void visitReadLabel(const ReadLabel &lab) { return DELEGATE_LABEL(MemAccessLabel); } void visitBWaitReadLabel(const BWaitReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } - void visitSpeculativeReadLabel(const SpeculativeReadLabel &lab) + void visitCondVarWaitReadLabel(const CondVarWaitReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } - void visitConfirmingReadLabel(const ConfirmingReadLabel &lab) + void visitSpeculativeReadLabel(const SpeculativeReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } - void visitDskReadLabel(const DskReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } - - void visitFaiReadLabel(const FaiReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } - void visitNoRetFaiReadLabel(const NoRetFaiReadLabel &lab) - { - return DELEGATE_LABEL(FaiReadLabel); - } - void visitBIncFaiReadLabel(const BIncFaiReadLabel &lab) + void visitConfirmingReadLabel(const ConfirmingReadLabel &lab) { - return DELEGATE_LABEL(FaiReadLabel); + return DELEGATE_LABEL(ReadLabel); } - void visitCasReadLabel(const CasReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } void visitLockCasReadLabel(const LockCasReadLabel &lab) { @@ -235,6 +138,15 @@ template class LabelVisitor { { return DELEGATE_LABEL(CasReadLabel); } + void visitFaiReadLabel(const FaiReadLabel &lab) { return DELEGATE_LABEL(ReadLabel); } + void visitNoRetFaiReadLabel(const NoRetFaiReadLabel &lab) + { + return DELEGATE_LABEL(FaiReadLabel); + } + void visitBIncFaiReadLabel(const BIncFaiReadLabel &lab) + { + return DELEGATE_LABEL(FaiReadLabel); + } void visitWriteLabel(const WriteLabel &lab) { return DELEGATE_LABEL(MemAccessLabel); } void visitUnlockWriteLabel(const UnlockWriteLabel &lab) @@ -246,17 +158,22 @@ template class LabelVisitor { { return DELEGATE_LABEL(WriteLabel); } - - void visitFaiWriteLabel(const FaiWriteLabel &lab) { return DELEGATE_LABEL(WriteLabel); } - void visitNoRetFaiWriteLabel(const NoRetFaiWriteLabel &lab) + void visitCondVarInitWriteLabel(const CondVarInitWriteLabel &lab) { - return DELEGATE_LABEL(FaiWriteLabel); + return DELEGATE_LABEL(WriteLabel); } - void visitBIncFaiWriteLabel(const BIncFaiWriteLabel &lab) + void visitCondVarSignalWriteLabel(const CondVarSignalWriteLabel &lab) { - return DELEGATE_LABEL(FaiWriteLabel); + return DELEGATE_LABEL(WriteLabel); + } + void visitCondVarBcastWriteLabel(const CondVarBcastWriteLabel &lab) + { + return DELEGATE_LABEL(WriteLabel); + } + void visitCondVarDestroyWriteLabel(const CondVarDestroyWriteLabel &lab) + { + return DELEGATE_LABEL(WriteLabel); } - void visitCasWriteLabel(const CasWriteLabel &lab) { return DELEGATE_LABEL(WriteLabel); } void visitLockCasWriteLabel(const LockCasWriteLabel &lab) { @@ -274,55 +191,45 @@ template class LabelVisitor { { return DELEGATE_LABEL(CasWriteLabel); } - - void visitDskWriteLabel(const DskWriteLabel &lab) { return DELEGATE_LABEL(WriteLabel); } - void visitDskMdWriteLabel(const DskMdWriteLabel &lab) { return DELEGATE_LABEL(WriteLabel); } - void visitDskJnlWriteLabel(const DskJnlWriteLabel &lab) + void visitFaiWriteLabel(const FaiWriteLabel &lab) { return DELEGATE_LABEL(WriteLabel); } + void visitNoRetFaiWriteLabel(const NoRetFaiWriteLabel &lab) { - return DELEGATE_LABEL(WriteLabel); + return DELEGATE_LABEL(FaiWriteLabel); } - void visitDskDirWriteLabel(const DskDirWriteLabel &lab) + void visitBIncFaiWriteLabel(const BIncFaiWriteLabel &lab) { - return DELEGATE_LABEL(WriteLabel); + return DELEGATE_LABEL(FaiWriteLabel); } void visitFenceLabel(const FenceLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitDskFsyncLabel(const DskFsyncLabel &lab) { return DELEGATE_LABEL(FenceLabel); } - void visitDskSyncLabel(const DskSyncLabel &lab) { return DELEGATE_LABEL(FenceLabel); } - void visitDskPbarrierLabel(const DskPbarrierLabel &lab) - { - return DELEGATE_LABEL(FenceLabel); - } - void visitSmpFenceLabelLKMM(const SmpFenceLabelLKMM &lab) - { - return DELEGATE_LABEL(FenceLabel); - } - void visitRCUSyncLabelLKMM(const RCUSyncLabelLKMM &lab) - { - return DELEGATE_LABEL(FenceLabel); - } + // void visitSubFenceLabel(const SubFenceLabel &lab) { return DELEGATE_LABEL(FenceLabel); } void visitMallocLabel(const MallocLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitFreeLabel(const FreeLabel &lab) { return DELEGATE_LABEL(EventLabel); } void visitHpRetireLabel(const HpRetireLabel &lab) { return DELEGATE_LABEL(FreeLabel); } - void visitHpProtectLabel(const HpProtectLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitLockLabelLAPOR(const LockLabelLAPOR &lab) { return DELEGATE_LABEL(EventLabel); } - void visitUnlockLabelLAPOR(const UnlockLabelLAPOR &lab) + void visitThreadCreateLabel(const ThreadCreateLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitThreadJoinLabel(const ThreadJoinLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitHpProtectLabel(const HpProtectLabel &lab) { return DELEGATE_LABEL(EventLabel); } void visitHelpingCasLabel(const HelpingCasLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitDskOpenLabel(const DskOpenLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitRCULockLabelLKMM(const RCULockLabelLKMM &lab) + void visitOptionalLabel(const OptionalLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitLoopBeginLabel(const LoopBeginLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitSpinStartLabel(const SpinStartLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitFaiZNESpinEndLabel(const FaiZNESpinEndLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitRCUUnlockLabelLKMM(const RCUUnlockLabelLKMM &lab) + void visitLockZNESpinEndLabel(const LockZNESpinEndLabel &lab) { return DELEGATE_LABEL(EventLabel); } - void visitCLFlushLabel(const CLFlushLabel &lab) { return DELEGATE_LABEL(EventLabel); } + void visitEmptyLabel(const EmptyLabel &lab) { return DELEGATE_LABEL(EventLabel); } + + /* Matchers for abstract classes */ /* * If none of the above matched, propagate to the next level. @@ -416,16 +323,10 @@ template class LabelPrinterBase : public LabelVisitor class LabelPrinterBase : public LabelVisitor { { out << "" << lab.getOrdering() << ""; } - void printFenceType(const SmpFenceLabelLKMM &lab) - { - out << "" << lab.getType() << ""; - } void visitFenceLabel(const FenceLabel &lab) { @@ -539,12 +424,6 @@ class DotPrinter : public LabelPrinterBase { printOrdering(lab); } - void visitSmpFenceLabelLKMM(const SmpFenceLabelLKMM &lab) - { - visitEventLabel(lab); - printFenceType(lab); - } - void visitThreadCreateLabel(const ThreadCreateLabel &lab) { visitEventLabel(lab); } void visitThreadJoinLabel(const ThreadJoinLabel &lab) { visitEventLabel(lab); } @@ -560,4 +439,4 @@ class DotPrinter : public LabelPrinterBase { void visitEventLabel(const EventLabel &lab) { out << lab.getKind(); } }; -#endif /* __LABEL_VISITOR_HPP__ */ +#endif /* GENMC_LABEL_VISITOR_HPP */ diff --git a/src/MaximalIterator.hpp b/src/ExecutionGraph/MaximalIterator.hpp similarity index 97% rename from src/MaximalIterator.hpp rename to src/ExecutionGraph/MaximalIterator.hpp index 286eab4..6a058f0 100644 --- a/src/MaximalIterator.hpp +++ b/src/ExecutionGraph/MaximalIterator.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MAXIMAL_ITERATOR_HPP__ -#define __MAXIMAL_ITERATOR_HPP__ +#ifndef GENMC_MAXIMAL_ITERATOR_HPP +#define GENMC_MAXIMAL_ITERATOR_HPP -#include "View.hpp" +#include "ADT/View.hpp" #include "config.h" #include #include diff --git a/src/Stamp.cpp b/src/ExecutionGraph/Stamp.cpp similarity index 100% rename from src/Stamp.cpp rename to src/ExecutionGraph/Stamp.cpp diff --git a/src/Stamp.hpp b/src/ExecutionGraph/Stamp.hpp similarity index 99% rename from src/Stamp.hpp rename to src/ExecutionGraph/Stamp.hpp index 99e4d7a..ef42716 100644 --- a/src/Stamp.hpp +++ b/src/ExecutionGraph/Stamp.hpp @@ -21,7 +21,7 @@ #ifndef GENMC_STAMP_HPP #define GENMC_STAMP_HPP -#include "Error.hpp" +#include "Support/Error.hpp" #include "config.h" #include diff --git a/src/IMMChecker.cpp b/src/IMMChecker.cpp deleted file mode 100644 index 672fc6b..0000000 --- a/src/IMMChecker.cpp +++ /dev/null @@ -1,2799 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "IMMChecker.hpp" - -void IMMChecker::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (llvm::isa(lab) && lab->isAtLeastAcquire() && !lab->isAtLeastRelease() || - llvm::isa(lab) && lab->isAtLeastAcquire() && lab->isAtLeastRelease() || - llvm::isa(lab) && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - if (llvm::isa(lab) && lab->isAtLeastAcquire() && !lab->isAtLeastRelease() || - llvm::isa(lab) && lab->isAtLeastAcquire() && lab->isAtLeastRelease() || - llvm::isa(lab) && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_3(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_4(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_5(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::entered; - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitCalc0_6(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::left; -} - -View IMMChecker::calculate0(const EventLabel *lab) -{ - View calcRes; - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_3.clear(); - visitedCalc0_3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_4.clear(); - visitedCalc0_4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_5.clear(); - visitedCalc0_5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_6.clear(); - visitedCalc0_6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -std::vector> IMMChecker::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector IMMChecker::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - return std::move(views); -} - -bool IMMChecker::isDepTracking() { return 1; } - -VerificationError IMMChecker::checkErrors(const EventLabel *lab) -{ - return VerificationError::VE_OK; -} - -bool IMMChecker::visitAcyclic0(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic0[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic0[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic1(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic1[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic1[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic2(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic2[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic3(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic2[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic3(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic3[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic3[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic4(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic4[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic4(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic4[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic5(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic5[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic5[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic6(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic6[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic6[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic7(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic7[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic7[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic8(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic8[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic8(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic8[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic9(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic9[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic9(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic9[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic10(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic10[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic11(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic10[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic11(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic11[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic9(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic11[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic12(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic12[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic12[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic13(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic13[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) if (llvm::isa(pLab) && pLab->isSC()) - { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic13[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic14(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic14[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic8(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) if (llvm::isa(pLab) && pLab->isSC()) - { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic14[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic15(const EventLabel *lab) -{ - auto &g = getGraph(); - - ++visitedAccepting; - visitedAcyclic15[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (llvm::isa(lab) && lab->isSC()) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab) && lab->isSC()) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic4(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab) && lab->isSC()) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - if (llvm::isa(pLab) && pLab->isSC()) - { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isSC()) { - auto &node = visitedAcyclic15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab) && lab->isSC()) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic14(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - --visitedAccepting; - visitedAcyclic15[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic16(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic16[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - for (auto *pLab : poloc_imm_preds(g, lab)) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && !pLab->isSC() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto *pLab : poloc_imm_preds(g, lab)) { - auto &node = visitedAcyclic16[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic16(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic16[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic17(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic17[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic17[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic17(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic17[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic18(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic18[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic19[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic19(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic18[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic19(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic19[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic18[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic18(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isAtLeastAcquire() || - llvm::isa(pLab) && pLab->isAtLeastAcquire() && - pLab->isAtLeastRelease() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic17[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic17(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic19[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic20(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic20[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) - if (pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastAcquire()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic19[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic19(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic20[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic21(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic21[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) if (llvm::isa(pLab) && pLab->isSC()) - { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic21[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic22(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic22[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic20[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic20(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &oLab : fr_imm_preds(g, lab)) - if (auto *pLab = &oLab; true) { - auto &node = visitedAcyclic21[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic21(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic22[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic22(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic22[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic23(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic23[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) - if (g.isRMWStore(pLab)) { - auto &node = visitedAcyclic24[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic24(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic23[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic24(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic24[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic24[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic25(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic25[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - visitedAcyclic25[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic26(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic26[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic26[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic26(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic26[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic27(const EventLabel *lab) -{ - auto &g = getGraph(); - - visitedAcyclic27[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic27[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic27(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - visitedAcyclic27[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::visitAcyclic28(const EventLabel *lab) -{ - auto &g = getGraph(); - - ++visitedAccepting; - visitedAcyclic28[lab->getStamp().get()] = {visitedAccepting, NodeStatus::entered}; - if (auto pLab = rfe_pred(g, lab); pLab) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - for (auto *pLab : detour_preds(g, lab)) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto *pLab : poloc_imm_preds(g, lab)) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isSC() || - llvm::isa(pLab) && pLab->isSC()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic28[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic28(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic26[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic26(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto *pLab : poloc_imm_preds(g, lab)) { - auto &node = visitedAcyclic16[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic16(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic25[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic25(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto &node = visitedAcyclic23[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic23(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab) && lab->isSC()) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic22[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic22(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic27[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic27(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic27[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic27(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting > node.count) - return false; - } - --visitedAccepting; - visitedAcyclic28[lab->getStamp().get()] = {visitedAccepting, NodeStatus::left}; - return true; -} - -bool IMMChecker::isAcyclic(const EventLabel *lab) -{ - visitedAccepting = 0; - visitedAcyclic0.clear(); - visitedAcyclic0.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1.clear(); - visitedAcyclic1.resize(g.getMaxStamp().get() + 1); - visitedAcyclic2.clear(); - visitedAcyclic2.resize(g.getMaxStamp().get() + 1); - visitedAcyclic3.clear(); - visitedAcyclic3.resize(g.getMaxStamp().get() + 1); - visitedAcyclic4.clear(); - visitedAcyclic4.resize(g.getMaxStamp().get() + 1); - visitedAcyclic5.clear(); - visitedAcyclic5.resize(g.getMaxStamp().get() + 1); - visitedAcyclic6.clear(); - visitedAcyclic6.resize(g.getMaxStamp().get() + 1); - visitedAcyclic7.clear(); - visitedAcyclic7.resize(g.getMaxStamp().get() + 1); - visitedAcyclic8.clear(); - visitedAcyclic8.resize(g.getMaxStamp().get() + 1); - visitedAcyclic9.clear(); - visitedAcyclic9.resize(g.getMaxStamp().get() + 1); - visitedAcyclic10.clear(); - visitedAcyclic10.resize(g.getMaxStamp().get() + 1); - visitedAcyclic11.clear(); - visitedAcyclic11.resize(g.getMaxStamp().get() + 1); - visitedAcyclic12.clear(); - visitedAcyclic12.resize(g.getMaxStamp().get() + 1); - visitedAcyclic13.clear(); - visitedAcyclic13.resize(g.getMaxStamp().get() + 1); - visitedAcyclic14.clear(); - visitedAcyclic14.resize(g.getMaxStamp().get() + 1); - visitedAcyclic15.clear(); - visitedAcyclic15.resize(g.getMaxStamp().get() + 1); - visitedAcyclic16.clear(); - visitedAcyclic16.resize(g.getMaxStamp().get() + 1); - visitedAcyclic17.clear(); - visitedAcyclic17.resize(g.getMaxStamp().get() + 1); - visitedAcyclic18.clear(); - visitedAcyclic18.resize(g.getMaxStamp().get() + 1); - visitedAcyclic19.clear(); - visitedAcyclic19.resize(g.getMaxStamp().get() + 1); - visitedAcyclic20.clear(); - visitedAcyclic20.resize(g.getMaxStamp().get() + 1); - visitedAcyclic21.clear(); - visitedAcyclic21.resize(g.getMaxStamp().get() + 1); - visitedAcyclic22.clear(); - visitedAcyclic22.resize(g.getMaxStamp().get() + 1); - visitedAcyclic23.clear(); - visitedAcyclic23.resize(g.getMaxStamp().get() + 1); - visitedAcyclic24.clear(); - visitedAcyclic24.resize(g.getMaxStamp().get() + 1); - visitedAcyclic25.clear(); - visitedAcyclic25.resize(g.getMaxStamp().get() + 1); - visitedAcyclic26.clear(); - visitedAcyclic26.resize(g.getMaxStamp().get() + 1); - visitedAcyclic27.clear(); - visitedAcyclic27.resize(g.getMaxStamp().get() + 1); - visitedAcyclic28.clear(); - visitedAcyclic28.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic0(lab) && visitAcyclic5(lab) && visitAcyclic6(lab) && - visitAcyclic8(lab) && visitAcyclic12(lab) && visitAcyclic13(lab) && - visitAcyclic15(lab) && visitAcyclic20(lab) && visitAcyclic21(lab); -} - -bool IMMChecker::isConsistent(const EventLabel *lab) { return isAcyclic(lab); } - -bool IMMChecker::isRecAcyclic(const EventLabel *lab) -{ - visitedRecAccepting = 0; - return true; -} - -bool IMMChecker::isRecoveryValid(const EventLabel *lab) { return isRecAcyclic(lab); } - -void IMMChecker::visitPPoRf0(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf0[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - visitedPPoRf0[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf1(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) - if (g.isRMWStore(pLab)) { - auto status = visitedPPoRf2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf2(pLab, pporf); - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - visitedPPoRf1[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf2(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - visitedPPoRf2[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf3(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf3[lab->getStamp().get()] = NodeStatus::entered; - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - visitedPPoRf3[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf4(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf4(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isAtLeastAcquire()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - visitedPPoRf4[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf5(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf5[lab->getStamp().get()] = NodeStatus::entered; - for (auto *pLab : poloc_imm_preds(g, lab)) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && !pLab->isSC() || - llvm::isa(pLab) && pLab->isSC()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto *pLab : poloc_imm_preds(g, lab)) { - auto status = visitedPPoRf5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf5(pLab, pporf); - } - visitedPPoRf5[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMChecker::visitPPoRf6(const EventLabel *lab, DepView &pporf) -{ - auto &g = getGraph(); - - visitedPPoRf6[lab->getStamp().get()] = NodeStatus::entered; - pporf.updateIdx(lab->getPos()); - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf4(pLab, pporf); - } - if (lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = rfe_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (llvm::isa(pLab) || pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto *pLab : detour_preds(g, lab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto *pLab : poloc_imm_preds(g, lab)) - if (llvm::isa(pLab) && pLab->isAtLeastRelease() && - !pLab->isSC() || - llvm::isa(pLab) && pLab->isSC()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (pLab->isAtLeastAcquire()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto *pLab : poloc_imm_preds(g, lab)) { - auto status = visitedPPoRf5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf5(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (g.isRMWStore(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (g.isRMWLoad(pLab)) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - visitedPPoRf6[lab->getStamp().get()] = NodeStatus::left; -} - -DepView IMMChecker::calcPPoRfBefore(const EventLabel *lab) -{ - DepView pporf; - pporf.updateIdx(lab->getPos()); - visitedPPoRf0.clear(); - visitedPPoRf0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf1.clear(); - visitedPPoRf1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf2.clear(); - visitedPPoRf2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf3.clear(); - visitedPPoRf3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf4.clear(); - visitedPPoRf4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf5.clear(); - visitedPPoRf5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf6.clear(); - visitedPPoRf6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitPPoRf6(lab, pporf); - return pporf; -} -std::unique_ptr IMMChecker::getPPoRfBefore(const EventLabel *lab) -{ - return LLVM_MAKE_UNIQUE(calcPPoRfBefore(lab)); -} - -const View &IMMChecker::getHbView(const EventLabel *lab) { return lab->view(0); } - -bool IMMChecker::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(0); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector IMMChecker::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto *lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool IMMChecker::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(0).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(0).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator IMMChecker::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator IMMChecker::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(0).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(0).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator IMMChecker::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector IMMChecker::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInitializer()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector IMMChecker::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(after), - [&](auto &rLab) { return rLab.getPos(); }); - }); - - return after; -} - -std::vector IMMChecker::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(after), - [&](auto &rLab) { return rLab.getPos(); }); - }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector IMMChecker::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(0); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(0).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(0).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -IMMChecker::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/IMMDriver.cpp b/src/IMMDriver.cpp deleted file mode 100644 index b01dd9a..0000000 --- a/src/IMMDriver.cpp +++ /dev/null @@ -1,2974 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "IMMDriver.hpp" -#include "ModuleInfo.hpp" - -IMMDriver::IMMDriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) - : GenMCDriver(conf, std::move(mod), std::move(MI), mode) -{} - -void IMMDriver::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_3(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_4(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_5(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc0_6(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::left; -} - -View IMMDriver::calculate0(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_3.clear(); - visitedCalc0_3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_4.clear(); - visitedCalc0_4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_5.clear(); - visitedCalc0_5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_6.clear(); - visitedCalc0_6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -void IMMDriver::visitCalc1_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc1_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_0(pLab, calcRes); - } - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitCalc1_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::left; -} - -View IMMDriver::calculate1(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc1_0.clear(); - visitedCalc1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_1.clear(); - visitedCalc1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_2.clear(); - visitedCalc1_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc1_1(lab, calcRes); - return calcRes; -} -std::vector> IMMDriver::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector IMMDriver::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - views.push_back(calculate1(lab)); - return std::move(views); -} - -void IMMDriver::updateMMViews(EventLabel *lab) -{ - lab->setCalculated(calculateSaved(lab)); - lab->setViews(calculateViews(lab)); -} - -bool IMMDriver::isDepTracking() const { return 1; } - -bool IMMDriver::visitInclusionLHS0_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab0 = lab; - return false; - } - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool IMMDriver::visitInclusionLHS0_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS0_0(pLab, v)) - return false; - } - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool IMMDriver::checkInclusion0(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS0_0.clear(); - visitedInclusionLHS0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS0_1.clear(); - visitedInclusionLHS0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS0_1(lab, v); -} - -VerificationError IMMDriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const -{ - return VerificationError::VE_OK; -} - -std::vector -IMMDriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const -{ - std::vector result; - - if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkInclusion0(lab)) { - racyLabs.push_back(racyLab0); - result.push_back(VerificationError::VE_WWRace); - } - - return result; -} - -bool IMMDriver::visitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_4(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_4[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_4[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_5[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_5[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_6(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_6[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_6[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_7(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_7[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && pLab->isSC() && - llvm::isa(pLab)) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_7[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_8(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_8[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_9(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_8[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_9(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_9[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_9[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_10(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_10[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_10[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_11(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_11[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_11[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_12(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_12[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_12[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_13(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_13[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_13[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_14(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_14[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_14[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic0_15(const EventLabel *lab) const -{ - auto &g = getGraph(); - - ++visitedAccepting0; - visitedAcyclic0_15[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - --visitedAccepting0; - visitedAcyclic0_15[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool IMMDriver::isAcyclic0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - if (!shouldVisitAcyclic0()) - return true; - - visitedAccepting0 = 0; - visitedAcyclic0_0.clear(); - visitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_1.clear(); - visitedAcyclic0_1.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_2.clear(); - visitedAcyclic0_2.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_3.clear(); - visitedAcyclic0_3.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_4.clear(); - visitedAcyclic0_4.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_5.clear(); - visitedAcyclic0_5.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_6.clear(); - visitedAcyclic0_6.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_7.clear(); - visitedAcyclic0_7.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_8.clear(); - visitedAcyclic0_8.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_9.clear(); - visitedAcyclic0_9.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_10.clear(); - visitedAcyclic0_10.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_11.clear(); - visitedAcyclic0_11.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_12.clear(); - visitedAcyclic0_12.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_13.clear(); - visitedAcyclic0_13.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_14.clear(); - visitedAcyclic0_14.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_15.clear(); - visitedAcyclic0_15.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic0_0(lab) && visitAcyclic0_1(lab) && visitAcyclic0_6(lab) && - visitAcyclic0_8(lab) && visitAcyclic0_10(lab) && visitAcyclic0_13(lab) && - visitAcyclic0_14(lab) && visitAcyclic0_15(lab); -} - -bool IMMDriver::shouldVisitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_0[lab->getStamp().get()] = NodeStatus::entered; - return false; - shouldVisitedAcyclic0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool IMMDriver::shouldVisitAcyclic0_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isSC()) - if (auto pLab = lab; true) { - auto &status = shouldVisitedAcyclic0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !shouldVisitAcyclic0_0(pLab)) - return false; - } - shouldVisitedAcyclic0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool IMMDriver::shouldVisitAcyclic0(void) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_0.clear(); - shouldVisitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - shouldVisitedAcyclic0_1.clear(); - shouldVisitedAcyclic0_1.resize(g.getMaxStamp().get() + 1); - return false || std::any_of(label_begin(g), label_end(g), - [&](auto &lab) { return !shouldVisitAcyclic0_1(&lab); }); -} - -bool IMMDriver::visitAcyclic1_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_0[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_0[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_1[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && pLab->isSC() && - llvm::isa(pLab)) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_1[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_2[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_2[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_3[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_3[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_4(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_4[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_4[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_5[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic1_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_5[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_6(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_6[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_6[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_7(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_7[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_7[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_8(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_8[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab))) && - pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_8[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_9(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_9[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_9(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_9[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_10(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_10[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_10[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_11(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic1_11[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - visitedAcyclic1_11[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::visitAcyclic1_12(const EventLabel *lab) const -{ - auto &g = getGraph(); - - ++visitedAccepting1; - visitedAcyclic1_12[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::entered}; - if (true && lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(0)) - { - auto &node = visitedAcyclic1_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_9(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (auto pLab = rfe_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - for (auto &tmp : detour_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastRelease() && - llvm::isa(pLab)) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab))) && - pLab->isDependable()) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic1_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic1_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic1_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting1 > node.count) - return false; - } - --visitedAccepting1; - visitedAcyclic1_12[lab->getStamp().get()] = {visitedAccepting1, NodeStatus::left}; - return true; -} - -bool IMMDriver::isAcyclic1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - if (!shouldVisitAcyclic1()) - return true; - - visitedAccepting1 = 0; - visitedAcyclic1_0.clear(); - visitedAcyclic1_0.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_1.clear(); - visitedAcyclic1_1.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_2.clear(); - visitedAcyclic1_2.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_3.clear(); - visitedAcyclic1_3.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_4.clear(); - visitedAcyclic1_4.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_5.clear(); - visitedAcyclic1_5.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_6.clear(); - visitedAcyclic1_6.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_7.clear(); - visitedAcyclic1_7.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_8.clear(); - visitedAcyclic1_8.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_9.clear(); - visitedAcyclic1_9.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_10.clear(); - visitedAcyclic1_10.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_11.clear(); - visitedAcyclic1_11.resize(g.getMaxStamp().get() + 1); - visitedAcyclic1_12.clear(); - visitedAcyclic1_12.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic1_0(lab) && visitAcyclic1_2(lab) && visitAcyclic1_4(lab); -} - -bool IMMDriver::isConsistent(const EventLabel *lab) const -{ - - return true && isAcyclic0(lab) && isAcyclic0(lab); -} - -bool IMMDriver::isRecAcyclic(const EventLabel *lab) const -{ - visitedRecAccepting = 0; - return true; -} - -bool IMMDriver::isRecoveryValid(const EventLabel *lab) const { return isRecAcyclic(lab); } - -void IMMDriver::visitPPoRf0(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf0[lab->getStamp().get()] = NodeStatus::entered; - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedPPoRf2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf2(pLab, pporf); - } - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (auto pLab = rfi_pred(g, lab); pLab) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - visitedPPoRf0[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf1(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - visitedPPoRf1[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf2(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab))) && - pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - visitedPPoRf2[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf3(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf3[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - visitedPPoRf3[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf4(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf4(pLab, pporf); - } - visitedPPoRf4[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf5(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf5[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedPPoRf5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf5(pLab, pporf); - } - visitedPPoRf5[lab->getStamp().get()] = NodeStatus::left; -} - -void IMMDriver::visitPPoRf6(const EventLabel *lab, DepView &pporf) const -{ - auto &g = getGraph(); - - visitedPPoRf6[lab->getStamp().get()] = NodeStatus::entered; - pporf.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = rfe_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) - if (true && pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - for (auto &tmp : detour_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastRelease() && - llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab))) && - pLab->isDependable()) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf6(pLab, pporf); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf4(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedPPoRf1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf1(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : ctrl_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : addr_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &p : data_preds(g, lab)) - if (auto *pLab = g.getEventLabel(p); true) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (true && llvm::isa(lab) && - ((llvm::isa(lab) && g.isRMWLoad(lab)) || - (llvm::isa(lab) && g.isRMWStore(lab)))) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedPPoRf0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf0(pLab, pporf); - } - if (true && llvm::isa(lab)) - for (auto &tmp : poloc_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedPPoRf5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf5(pLab, pporf); - } - if (true && lab->isAtLeastRelease()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedPPoRf3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitPPoRf3(pLab, pporf); - } - visitedPPoRf6[lab->getStamp().get()] = NodeStatus::left; -} - -DepView IMMDriver::calcPPoRfBefore(const EventLabel *lab) const -{ - auto &g = getGraph(); - DepView pporf; - pporf.updateIdx(lab->getPos()); - visitedPPoRf0.clear(); - visitedPPoRf0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf1.clear(); - visitedPPoRf1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf2.clear(); - visitedPPoRf2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf3.clear(); - visitedPPoRf3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf4.clear(); - visitedPPoRf4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf5.clear(); - visitedPPoRf5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedPPoRf6.clear(); - visitedPPoRf6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitPPoRf6(lab, pporf); - return pporf; -} -std::unique_ptr IMMDriver::calculatePrefixView(const EventLabel *lab) const -{ - return std::make_unique(calcPPoRfBefore(lab)); -} - -const View &IMMDriver::getHbView(const EventLabel *lab) const { return lab->view(0); } - -bool IMMDriver::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(0); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector IMMDriver::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto &lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(&lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool IMMDriver::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(0).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(0).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator IMMDriver::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator IMMDriver::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(0).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(0).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator IMMDriver::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector IMMDriver::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInit()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector IMMDriver::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - std::vector rfAfter; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - return after; -} - -std::vector IMMDriver::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector IMMDriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(0); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(0).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(0).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -IMMDriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/IMMDriver.hpp b/src/IMMDriver.hpp deleted file mode 100644 index 9a41692..0000000 --- a/src/IMMDriver.hpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#ifndef __IMM_DRIVER_HPP__ -#define __IMM_DRIVER_HPP__ - -#include "ExecutionGraph.hpp" -#include "GenMCDriver.hpp" -#include "GraphIterators.hpp" -#include "MaximalIterator.hpp" -#include "VSet.hpp" -#include "VerificationError.hpp" -#include "config.h" -#include -#include - -class IMMDriver : public GenMCDriver { - -private: - enum class NodeStatus : unsigned char { unseen, entered, left }; - - struct NodeCountStatus { - NodeCountStatus() = default; - NodeCountStatus(uint16_t c, NodeStatus s) : count(c), status(s) {} - uint16_t count = 0; - NodeStatus status = NodeStatus::unseen; - }; - -public: - IMMDriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); - - std::vector> calculateSaved(const EventLabel *lab); - std::vector calculateViews(const EventLabel *lab); - void updateMMViews(EventLabel *lab) override; - bool isDepTracking() const override; - bool isConsistent(const EventLabel *lab) const override; - VerificationError checkErrors(const EventLabel *lab, - const EventLabel *&race) const override; - std::vector - checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const; - bool isRecoveryValid(const EventLabel *lab) const override; - std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; - const View &getHbView(const EventLabel *lab) const override; - std::vector getCoherentStores(SAddr addr, Event read) override; - std::vector getCoherentRevisits(const WriteLabel *sLab, - const VectorClock &pporf) override; - llvm::iterator_range - getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; - -private: - bool isWriteRfBefore(Event a, Event b); - std::vector getInitRfsAtLoc(SAddr addr); - bool isHbOptRfBefore(const Event e, const Event write); - ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); - ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); - ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); - std::vector getMOOptRfAfter(const WriteLabel *sLab); - std::vector getMOInvOptRfAfter(const WriteLabel *sLab); - - void visitCalc0_0(const EventLabel *lab, View &calcRes); - void visitCalc0_1(const EventLabel *lab, View &calcRes); - void visitCalc0_2(const EventLabel *lab, View &calcRes); - void visitCalc0_3(const EventLabel *lab, View &calcRes); - void visitCalc0_4(const EventLabel *lab, View &calcRes); - void visitCalc0_5(const EventLabel *lab, View &calcRes); - void visitCalc0_6(const EventLabel *lab, View &calcRes); - - View calculate0(const EventLabel *lab); - - mutable std::vector visitedCalc0_0; - mutable std::vector visitedCalc0_1; - mutable std::vector visitedCalc0_2; - mutable std::vector visitedCalc0_3; - mutable std::vector visitedCalc0_4; - mutable std::vector visitedCalc0_5; - mutable std::vector visitedCalc0_6; - - void visitCalc1_0(const EventLabel *lab, View &calcRes); - void visitCalc1_1(const EventLabel *lab, View &calcRes); - void visitCalc1_2(const EventLabel *lab, View &calcRes); - - View calculate1(const EventLabel *lab); - - mutable std::vector visitedCalc1_0; - mutable std::vector visitedCalc1_1; - mutable std::vector visitedCalc1_2; - - bool visitInclusionLHS0_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS0_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion0(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS0_0; - mutable std::vector visitedInclusionLHS0_1; - mutable std::vector visitedInclusionRHS0_0; - mutable std::vector visitedInclusionRHS0_1; - - mutable std::vector lhsAccept0; - mutable std::vector rhsAccept0; - - mutable const EventLabel *racyLab0 = nullptr; - - bool visitAcyclic0_0(const EventLabel *lab) const; - bool visitAcyclic0_1(const EventLabel *lab) const; - bool visitAcyclic0_2(const EventLabel *lab) const; - bool visitAcyclic0_3(const EventLabel *lab) const; - bool visitAcyclic0_4(const EventLabel *lab) const; - bool visitAcyclic0_5(const EventLabel *lab) const; - bool visitAcyclic0_6(const EventLabel *lab) const; - bool visitAcyclic0_7(const EventLabel *lab) const; - bool visitAcyclic0_8(const EventLabel *lab) const; - bool visitAcyclic0_9(const EventLabel *lab) const; - bool visitAcyclic0_10(const EventLabel *lab) const; - bool visitAcyclic0_11(const EventLabel *lab) const; - bool visitAcyclic0_12(const EventLabel *lab) const; - bool visitAcyclic0_13(const EventLabel *lab) const; - bool visitAcyclic0_14(const EventLabel *lab) const; - bool visitAcyclic0_15(const EventLabel *lab) const; - - bool isAcyclic0(const EventLabel *lab) const; - - mutable std::vector visitedAcyclic0_0; - mutable std::vector visitedAcyclic0_1; - mutable std::vector visitedAcyclic0_2; - mutable std::vector visitedAcyclic0_3; - mutable std::vector visitedAcyclic0_4; - mutable std::vector visitedAcyclic0_5; - mutable std::vector visitedAcyclic0_6; - mutable std::vector visitedAcyclic0_7; - mutable std::vector visitedAcyclic0_8; - mutable std::vector visitedAcyclic0_9; - mutable std::vector visitedAcyclic0_10; - mutable std::vector visitedAcyclic0_11; - mutable std::vector visitedAcyclic0_12; - mutable std::vector visitedAcyclic0_13; - mutable std::vector visitedAcyclic0_14; - mutable std::vector visitedAcyclic0_15; - - mutable uint16_t visitedAccepting0 = 0; - bool shouldVisitAcyclic0_0(const EventLabel *lab) const; - bool shouldVisitAcyclic0_1(const EventLabel *lab) const; - - bool shouldVisitAcyclic0(void) const; - - mutable std::vector shouldVisitedAcyclic0_0; - mutable std::vector shouldVisitedAcyclic0_1; - - bool visitAcyclic1_0(const EventLabel *lab) const; - bool visitAcyclic1_1(const EventLabel *lab) const; - bool visitAcyclic1_2(const EventLabel *lab) const; - bool visitAcyclic1_3(const EventLabel *lab) const; - bool visitAcyclic1_4(const EventLabel *lab) const; - bool visitAcyclic1_5(const EventLabel *lab) const; - bool visitAcyclic1_6(const EventLabel *lab) const; - bool visitAcyclic1_7(const EventLabel *lab) const; - bool visitAcyclic1_8(const EventLabel *lab) const; - bool visitAcyclic1_9(const EventLabel *lab) const; - bool visitAcyclic1_10(const EventLabel *lab) const; - bool visitAcyclic1_11(const EventLabel *lab) const; - bool visitAcyclic1_12(const EventLabel *lab) const; - - bool isAcyclic1(const EventLabel *lab) const; - - mutable std::vector visitedAcyclic1_0; - mutable std::vector visitedAcyclic1_1; - mutable std::vector visitedAcyclic1_2; - mutable std::vector visitedAcyclic1_3; - mutable std::vector visitedAcyclic1_4; - mutable std::vector visitedAcyclic1_5; - mutable std::vector visitedAcyclic1_6; - mutable std::vector visitedAcyclic1_7; - mutable std::vector visitedAcyclic1_8; - mutable std::vector visitedAcyclic1_9; - mutable std::vector visitedAcyclic1_10; - mutable std::vector visitedAcyclic1_11; - mutable std::vector visitedAcyclic1_12; - - mutable uint16_t visitedAccepting1 = 0; - bool shouldVisitAcyclic1(void) const { return true; }; - - bool isRecAcyclic(const EventLabel *lab) const; - - mutable uint16_t visitedRecAccepting = 0; - void visitPPoRf0(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf1(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf2(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf3(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf4(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf5(const EventLabel *lab, DepView &pporf) const; - void visitPPoRf6(const EventLabel *lab, DepView &pporf) const; - - DepView calcPPoRfBefore(const EventLabel *lab) const; - - mutable std::vector visitedPPoRf0; - mutable std::vector visitedPPoRf1; - mutable std::vector visitedPPoRf2; - mutable std::vector visitedPPoRf3; - mutable std::vector visitedPPoRf4; - mutable std::vector visitedPPoRf5; - mutable std::vector visitedPPoRf6; - - mutable std::vector> saved; - mutable std::vector views; -}; - -#endif /* __IMM_DRIVER_HPP__ */ diff --git a/src/Interpreter.h b/src/Interpreter.h deleted file mode 100644 index 1d25673..0000000 --- a/src/Interpreter.h +++ /dev/null @@ -1,888 +0,0 @@ -// For the parts of the code originating from LLVM-3.5: -//===-- Interpreter.h ------------------------------------------*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LLVMLICENSE for details. -// -//===----------------------------------------------------------------------===// -// -// This header file defines the interpreter structure -// -//===----------------------------------------------------------------------===// - -/* - * (For the parts of the code modified from LLVM-3.5) - * - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#include "config.h" - -#ifndef LLI_INTERPRETER_H -#define LLI_INTERPRETER_H - -#include "InterpreterEnumAPI.hpp" -#include "Config.hpp" -#include "DepTracker.hpp" -#include "MemAccess.hpp" -#include "ModuleInfo.hpp" -#include "ThreadInfo.hpp" -#include "SAddr.hpp" -#include "SAddrAllocator.hpp" -#include "SVal.hpp" -#include "View.hpp" -#include "CallInstWrapper.hpp" -#include "VerificationError.hpp" -#include "value_ptr.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Some helpers for GenericValues */ -#define INT_TO_GV(typ, val) \ -({ \ - llvm::GenericValue __ret; \ - __ret.IntVal = llvm::APInt((typ)->getIntegerBitWidth(), (val), true); \ - __ret; \ -}) - -#define PTR_TO_GV(ptr) \ -({ \ - llvm::GenericValue __ret; \ - __ret.PointerVal = (void *) (ptr); \ - __ret; \ -}) - -#define GET_ZERO_GV(typ) \ -({ \ - llvm::GenericValue __ret; \ - if (typ->isPointerTy()) \ - __ret = PTR_TO_GV(nullptr); \ - else \ - __ret = INT_TO_GV(typ, 0); \ - __ret; \ -}) - -class GenMCDriver; - -#define INT_TO_GV(typ, val) \ -({ \ - llvm::GenericValue __ret; \ - __ret.IntVal = llvm::APInt((typ)->getIntegerBitWidth(), (val), true); \ - __ret; \ -}) - -#define PTR_TO_GV(ptr) \ -({ \ - llvm::GenericValue __ret; \ - __ret.PointerVal = (void *) (ptr); \ - __ret; \ -}) - -namespace llvm { - -class IntrinsicLowering; -struct FunctionInfo; -template class generic_gep_type_iterator; -class ConstantExpr; -typedef generic_gep_type_iterator gep_type_iterator; - -typedef std::vector ValuePlaneTy; - -// AllocaHolder - Object to track all of the blocks of memory allocated by -// allocas in a particular stack frame. Since the driver needs to be made -// aware of the deallocs, special care needs to be taken to inform the driver -// when stack frames are popped -// -class AllocaHolder { - std::vector allocas; - - public: - using Allocas = std::vector; - - AllocaHolder() {} - - void add(void *mem) { allocas.push_back(mem); } - const Allocas &get() const { return allocas; } -}; - -// ExecutionContext struct - This struct represents one stack frame currently -// executing. -// -struct ExecutionContext { - Function *CurFunction;// The currently executing function - BasicBlock *CurBB; // The currently executing BB - BasicBlock::iterator CurInst; // The next instruction to execute - CallInstWrapper Caller; // Holds the call that called subframes. - // NULL if main func or debugger invoked fn - std::map Values; // LLVM values used in this invocation - std::vector VarArgs; // Values passed through an ellipsis - AllocaHolder Allocas; // Track memory allocated by alloca - - ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} -}; - -/* The different reasons a thread might block */ -enum class BlockageType { - NotBlocked, - ThreadJoin, - Spinloop, - FaiZNESpinloop, - LockZNESpinloop, - HelpedCas, - Confirmation, - ReadOptBlock, - LockNotAcq, - LockNotRel, - Barrier, - Cons, - Error, - User, -}; - -/* - * Thread class -- Contains information specific to each thread. - */ -class Thread { - -public: - using MyRNG = std::minstd_rand; - using MyDist = std::uniform_int_distribution; - static constexpr int seed = 1995; - - int id; - int parentId; - llvm::Function *threadFun; - SVal threadArg; - std::vector ECStack; - std::vector initEC; - std::unordered_map tls; - unsigned int globalInstructions; - unsigned int globalInstSnap; - BasicBlock::iterator curInstSnap; - BlockageType blocked; - MyRNG rng; - std::vector > prefixLOC; - - bool isMain() const { return id == 0; } - - void block(BlockageType t) { blocked = t; } - void unblock() { blocked = BlockageType::NotBlocked; } - bool isBlocked() const { return blocked != BlockageType::NotBlocked; } - BlockageType getBlockageType() const { return blocked; } - - /* Useful for one-to-many instr->events correspondence */ - void takeSnapshot() { - globalInstSnap = globalInstructions; - curInstSnap = --ECStack.back().CurInst; - ++ECStack.back().CurInst; - } - void rollToSnapshot() { - globalInstructions = globalInstSnap; - ECStack.back().CurInst = curInstSnap; - } - -protected: - friend class Interpreter; - - Thread(llvm::Function *F, int id) - : id(id), parentId(-1), threadFun(F), initEC(), globalInstructions(0), - blocked(BlockageType::NotBlocked), rng(seed) {} - - Thread(llvm::Function *F, SVal arg, int id, int pid, const llvm::ExecutionContext &SF) - : id(id), parentId(pid), threadFun(F), threadArg(arg), - initEC({SF}), globalInstructions(0), blocked(BlockageType::NotBlocked), rng(seed) {} -}; - -llvm::raw_ostream& operator<<(llvm::raw_ostream &s, const Thread &thr); - -/* Pers: The state of the program -- i.e., part of the program being interpreted */ -enum class ProgramState { - Ctors, - Main, - Dtors, - Recovery -}; - -/* The state of the current execution */ -enum class ExecutionState { - Normal, - Replay -}; - -struct DynamicComponents { - - /* Information about threads as well as the currently executing thread */ - std::vector threads; - int currentThread = 0; - - /* Pointer to the dependency tracker */ - value_ptr depTracker = nullptr; - - /* Information about the interpreter's state */ - ExecutionState execState = ExecutionState::Normal; - ProgramState programState = ProgramState::Main; /* Pers */ - - /* Pers: A map from file descriptors to file descriptions */ - llvm::IndexedMap fdToFile; - - /* Pers: Maps a filename to the address of the contents of the directory's inode for - * said name (the contents should have the address of the file's inode) */ - std::unordered_map nameToInodeAddr; - - GenericValue ExitValue; // The return value of the called function - - // AtExitHandlers - List of functions to call when the program exits, - // registered with the atexit() library function. - std::vector AtExitHandlers; -}; - -using InterpreterState = DynamicComponents; - -// Interpreter - This class represents the entirety of the interpreter. -// -class Interpreter : public ExecutionEngine, public InstVisitor { - -public: - using AnnotID = ModuleID::ID; - using AnnotT = SExpr; - -protected: - - /*** Static components (once set, do not change) ***/ - - /* Information about the module under test */ - std::unique_ptr MI; - - /* List of thread-local variables, with their initializing values */ - std::unordered_map threadLocalVars; - - /* Mapping between static allocation beginning and the actual addresses of - * global variables (where their contents are stored) */ - std::unordered_map staticValueMap; - - /* Keep all static ranges that have been allocated */ - VSet > staticAllocas; - - /* Maintain the relationship between SAddr and global variables, - * so that we can get naming information */ - std::unordered_map staticNames; - - /* (Composition) pointer to the driver */ - GenMCDriver *driver; - - Function *mainFun = nullptr; - - /* Whether the driver should be called on system errors */ - bool stopOnSystemErrors; - - /* Where system errors return values should be stored (if required) */ - SAddr errnoAddr; - Type *errnoTyp; - - /* Pers: The recovery routine to run */ - Function *recoveryRoutine = nullptr; - - /* This is not exactly static but is reset to the same value each time*/ - std::vector mainECStack; - - IntrinsicLowering *IL; - - /*** Dynamic components (change during verification) ***/ - - DynamicComponents dynState; - -public: - explicit Interpreter(std::unique_ptr M, std::unique_ptr MI, - GenMCDriver *driver, const Config *userConf, SAddrAllocator &alloctor); - virtual ~Interpreter(); - - std::unique_ptr saveState(); - void restoreState(std::unique_ptr); - - Thread &constructAddThreadFromInfo(const ThreadInfo &ti) { - auto *calledFun = dyn_cast(const_cast(MI->idInfo.IDV.at(ti.funId))); - BUG_ON(!calledFun); - ExecutionContext SF; - - SF.CurFunction = calledFun; - SF.CurBB = &calledFun->front(); - SF.CurInst = SF.CurBB->begin(); - - SF.Values[&*calledFun->arg_begin()] = PTR_TO_GV(ti.arg.get()); - return createAddNewThread(calledFun, ti.arg, ti.id, ti.parentId, SF); - } - void setExecutionContext(const std::vector &tis) { - dynState.threads.clear(); - createAddMainThread(); - for (auto &ti : tis) - constructAddThreadFromInfo(ti); - } - -#define CALL_DRIVER(method, ...) \ - ({ \ - if (getProgramState() != ProgramState::Recovery || \ - #method != "handleLoad") { \ - incPos(); \ - } \ - driver->method(__VA_ARGS__); \ - }) - -/* When replaying, we don't decrease the pos so we don't get into an - * infinite loop, e.g., if the last instruction reads bottom. - * (Besides, the amount of replaying should be well-defined.) - */ -#define CALL_DRIVER_RESET_IF_NONE(method, ...) \ - ({ \ - incPos(); \ - auto ret = driver->method(__VA_ARGS__); \ - if (!ret.has_value() && getExecState() != ExecutionState::Replay) { \ - decPos(); \ - --ECStack().back().CurInst; \ - } else if (getProgramState() == ProgramState::Recovery && \ - #method == "handleLoad") { \ - decPos(); \ - } \ - ret; \ - }) - -#define CALL_DRIVER_RESET_IF_FALSE(method, ...) \ - ({ \ - incPos(); \ - auto ret = driver->method(__VA_ARGS__); \ - if (!ret) { \ - decPos(); \ - --ECStack().back().CurInst; \ - } \ - ret; \ - }) - - /* Blocks the current execution */ - void block(BlockageType t = BlockageType::Error ) { - std::for_each(threads_begin(), threads_end(), [&](Thread &thr){ thr.block(t); }); - } - - /* Resets all thread info to their initial values */ - void resetThread(unsigned int id); - - /* Resets the interpreter at the beginning of a new execution */ - void reset(); - - /* Pers: Setups the execution context for the recovery routine - * in thread TID. Assumes that the thread has already been added - * to the thread list. */ - void setupRecoveryRoutine(int tid); - - /* Pers: Does cleanups after the recovery routine has run */ - void cleanupRecoveryRoutine(int tid); - - /* Creates a new thread and adds it to the thread list */ - Thread &createAddNewThread(llvm::Function *F, SVal arg, int tid, int pid, - const llvm::ExecutionContext &SF); - - /* Pers: Creates a thread for the recovery routine and adds it to - * the thread list */ - Thread &createAddRecoveryThread(int tid); - - /* Sets-up the specified thread for execution */ - void scheduleThread(int tid) { dynState.currentThread = tid; } - - /* Returns the currently executing thread */ - Thread& getCurThr() { return dynState.threads[dynState.currentThread]; } - const Thread &getCurThr() const { return dynState.threads.at(dynState.currentThread); } - - /* Returns the thread with the specified ID (taken from the graph) */ - Thread& getThrById(int id) { return dynState.threads[id]; }; - const Thread& getThrById(int id) const { return dynState.threads[id]; }; - - unsigned int getNumThreads() const { return dynState.threads.size(); } - - using thread_iterator = std::vector::iterator; - using const_thread_iterator = std::vector::const_iterator; - using thread_range = iterator_range; - using const_thread_range = iterator_range; - - const_thread_iterator threads_begin() const { return dynState.threads.begin(); } - const_thread_iterator threads_end() const { return dynState.threads.end(); } - thread_iterator threads_begin() { return dynState.threads.begin(); } - thread_iterator threads_end() { return dynState.threads.end(); } - const_thread_range threads() const { return const_thread_range(threads_begin(), threads_end()); } - thread_range threads() { return thread_range(threads_begin(), threads_end()); } - - /* Returns the stack frame of the currently executing thread */ - std::vector &ECStack() { return getCurThr().ECStack; } - - /* Returns the current (global) position (thread, index) interpreted */ - Event currPos() const { return Event(getCurThr().id, getCurThr().globalInstructions); }; - Event nextPos() const { return currPos().next(); }; - Event incPos() { - auto &thr = getCurThr(); - return Event(thr.id, ++thr.globalInstructions); - }; - Event decPos() { - auto &thr = getCurThr(); - return Event(thr.id, --thr.globalInstructions); - }; - - /* Query interpreter's state */ - ProgramState getProgramState() const { return dynState.programState; } - ExecutionState getExecState() const { return dynState.execState; } - - /* Annotation information */ - - /* Returns annotation information for the instruction I */ - const AnnotT *getAnnotation(Instruction *I) const { - auto id = MI->idInfo.VID[I]; - return MI->annotInfo.annotMap.count(id) ? MI->annotInfo.annotMap.at(id).get() : nullptr; - } - - /* Returns (concretized) annotation information for the - * current instruction (assuming we're executing it) */ - std::unique_ptr getCurrentAnnotConcretized(); - - /* Memory pools checks */ - - /* Returns true if the interpreter has allocated space for the specified static */ - bool isStaticallyAllocated(SAddr addr) const; - void *getStaticAddr(SAddr addr) const; - std::string getStaticName(SAddr addr) const; - - /// runAtExitHandlers - Run any functions registered by the program's calls to - /// atexit(3), which we intercept and store in AtExitHandlers. - /// - void runAtExitHandlers(); - - /// create - Create an interpreter ExecutionEngine. This can never fail. - /// - static std::unique_ptr - create(std::unique_ptr M, std::unique_ptr MI, - GenMCDriver *driver, const Config *userConf, - SAddrAllocator &alloctor, std::string *ErrorStr = nullptr); - - /// run - Start execution with the specified function and arguments. - /// -#ifdef LLVM_EXECUTION_ENGINE_RUN_FUNCTION_VECTOR - virtual GenericValue runFunction(Function *F, - const std::vector &ArgValues); -#else - virtual GenericValue runFunction(Function *F, - llvm::ArrayRef ArgValues); -#endif - - void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - // FIXME: not implemented. - return nullptr; - } - - void *getPointerToNamedFunction(llvm::StringRef Name, - bool AbortOnFailure = true) { - // FIXME: not implemented. - return nullptr; - }; - - /// recompileAndRelinkFunction - For the interpreter, functions are always - /// up-to-date. - /// - void *recompileAndRelinkFunction(Function *F) { - return getPointerToFunction(F); - } - - /// freeMachineCodeForFunction - The interpreter does not generate any code. - /// - void freeMachineCodeForFunction(Function *F) { } - - - /* Helper functions */ - void replayExecutionBefore(const VectorClock &before); - - SVal getLocInitVal(const AAccess &access) { - GenericValue result; - - LoadValueFromMemory(result, (llvm::GenericValue *) getStaticAddr(access.getAddr()), - IntegerType::get(Modules.back()->getContext(), access.getSize().get() * 8)); - return SVal(result.IntVal.getLimitedValue()); - } - - unsigned int getTypeSize(Type *typ) const; - SVal executeAtomicRMWOperation(SVal oldVal, SVal val, ASize size, AtomicRMWInst::BinOp op); - - // Methods used to execute code: - // Place a call on the stack - void callFunction(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps); - - /* callFunction() wrappers to be called before running a function */ - void setupFunctionCall(Function *F, ArrayRef ArgValues); - void setupStaticCtorsDtors(Module &M, bool isDtors); - void setupStaticCtorsDtors(bool isDtors); - void setupMain(Function *Fn, - const std::vector &argv, - const char * const * envp); - - void run(); // Execute instructions until nothing left to do - - /* run() wrappers */ - int runAsMain(const std::string &main); - void runRecovery(); - - // Opcode Implementations - void visitReturnInst(ReturnInst &I); - void visitBranchInst(BranchInst &I); - void visitSwitchInst(SwitchInst &I); - void visitIndirectBrInst(IndirectBrInst &I); - - void visitBinaryOperator(BinaryOperator &I); - void visitICmpInst(ICmpInst &I); - void visitFCmpInst(FCmpInst &I); - void visitAllocaInst(AllocaInst &I); - void visitLoadInst(LoadInst &I); - void visitStoreInst(StoreInst &I); - void visitGetElementPtrInst(GetElementPtrInst &I); - void visitPHINode(PHINode &PN) { - llvm_unreachable("PHI nodes already handled!"); - } - void visitTruncInst(TruncInst &I); - void visitZExtInst(ZExtInst &I); - void visitSExtInst(SExtInst &I); - void visitFPTruncInst(FPTruncInst &I); - void visitFPExtInst(FPExtInst &I); - void visitUIToFPInst(UIToFPInst &I); - void visitSIToFPInst(SIToFPInst &I); - void visitFPToUIInst(FPToUIInst &I); - void visitFPToSIInst(FPToSIInst &I); - void visitPtrToIntInst(PtrToIntInst &I); - void visitIntToPtrInst(IntToPtrInst &I); - void visitBitCastInst(BitCastInst &I); - void visitSelectInst(SelectInst &I); - - void visitCallInstWrapper(CallInstWrapper CIW); -#if LLVM_VERSION_MAJOR < 11 - void visitCallSite(CallSite CS) { visitCallInstWrapper(CallInstWrapper(CS)); } -#else - void visitCallBase(CallBase &CB) { visitCallInstWrapper(CallInstWrapper(CB)); } -#endif - void visitUnreachableInst(UnreachableInst &I); - - void visitShl(BinaryOperator &I); - void visitLShr(BinaryOperator &I); - void visitAShr(BinaryOperator &I); - - void visitVAArgInst(VAArgInst &I); - void visitExtractElementInst(ExtractElementInst &I); - void visitInsertElementInst(InsertElementInst &I); - void visitShuffleVectorInst(ShuffleVectorInst &I); - - void visitExtractValueInst(ExtractValueInst &I); - void visitInsertValueInst(InsertValueInst &I); - - void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I); - void visitAtomicRMWInst(AtomicRMWInst &I); - void visitFenceInst(FenceInst &I); - - bool isInlineAsm(CallInstWrapper CIW, std::string *asmStr); - void visitInlineAsm(CallInstWrapper CIW, const std::string &asmString); - - void visitInstruction(Instruction &I) { - errs() << I << "\n"; - llvm_unreachable("Instruction not interpretable yet!"); - } - - GenericValue callExternalFunction(Function *F, - const std::vector &ArgVals); - void exitCalled(GenericValue GV); - - void addAtExitHandler(Function *F) { - dynState.AtExitHandlers.push_back(F); - } - - GenericValue *getFirstVarArg () { - return &(ECStack().back ().VarArgs[0]); - } - -private: // Helper functions - GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, - gep_type_iterator E, ExecutionContext &SF); - - // SwitchToNewBasicBlock - Start execution in a new basic block and run any - // PHI nodes in the top of the block. This is used for intraprocedural - // control flow. - // - void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); - - void *getPointerToFunction(Function *F) { return (void*)F; } - void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; } - - void initializeExecutionEngine() { } - void initializeExternalFunctions(); - GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); - GenericValue getOperandValue(Value *V, ExecutionContext &SF); - GenericValue executeTruncInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeSExtInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeZExtInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, - ExecutionContext &SF); - GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, - Type *Ty, ExecutionContext &SF); - std::vector translateExternalCallArgs(Function *F, - const std::vector &Args) const; - void returnValueToCaller(Type *RetTy, GenericValue Result); - void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result, ReturnInst *retI = nullptr); - - void handleSystemError(SystemError code, const std::string &msg); - - SVal getInodeTransStatus(void *inode, Type *intTyp); - void setInodeTransStatus(void *inode, Type *intTyp, SVal status); - SVal readInodeSizeFS(void *inode, Type *intTyp, - const std::unique_ptr &deps); - void updateInodeSizeFS(void *inode, Type *intTyp, SVal newSize, - const std::unique_ptr &deps); - void updateInodeDisksizeFS(void *inode, Type *intTyp, SVal newSize, - SVal ordDataBegin, SVal ordDataEnd); - void writeDataToDisk(void *buf, int bufOffset, void *inode, int inodeOffset, - int count, Type *dataTyp, const std::unique_ptr &deps); - void readDataFromDisk(void *inode, int inodeOffset, void *buf, int bufOffset, - int count, Type *dataTyp, const std::unique_ptr &deps); - void updateDirNameInode(const std::string &name, Type *intTyp, SVal inode); - - SVal checkOpenFlagsFS(SVal &flags, Type *intTyp); - SVal executeInodeLookupFS(const std::string &name, Type *intTyp); - SVal executeInodeCreateFS(const std::string &name, Type *intTyp, - const std::unique_ptr &deps); - SVal executeLookupOpenFS(const std::string &filename, SVal &flags, Type *intTyp, - const std::unique_ptr &deps); - SVal executeOpenFS(const std::string &filename, SVal flags, SVal inode, Type *intTyp, - const std::unique_ptr &deps); - - void executeReleaseFileFS(void *fileDesc, Type *intTyp, const std::unique_ptr &deps); - SVal executeCloseFS(SVal fd, Type *intTyp, const std::unique_ptr &deps); - SVal executeRenameFS(const std::string &oldpath, SVal oldInode, const std::string &newpath, - SVal newInode, Type *intTyp); - SVal executeLinkFS(const std::string &newpath, SVal oldInode, Type *intTyp); - SVal executeUnlinkFS(const std::string &pathname, Type *intTyp); - - - SVal executeTruncateFS(SVal inode, SVal length, Type *intTyp, - const std::unique_ptr &deps); - SVal executeReadFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, - SVal count, const std::unique_ptr &deps); - void zeroDskRangeFS(void *inode, SVal start, SVal end, Type *writeIntTyp); - SVal executeWriteChecksFS(void *inode, Type *intTyp, SVal flags, SVal offset, SVal count, - SVal &wOffset, const std::unique_ptr &deps); - bool shouldUpdateInodeDisksizeFS(void *inode, Type *intTyp, SVal size, - SVal offset, SVal count, SVal &dSize); - SVal executeBufferedWriteFS(void *inode, Type *intTyp, void *buf, Type *bufElemTyp, SVal wOffset, - SVal count, const std::unique_ptr &deps); - SVal executeWriteFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, SVal count, - const std::unique_ptr &deps); - SVal executeLseekFS(void *file, Type *intTyp, SVal offset, SVal whence, - const std::unique_ptr &deps); - void executeFsyncFS(void *inode, Type *intTyp); - - void setProgramState(ProgramState s) { dynState.programState = s; } - void setExecState(ExecutionState s) { dynState.execState = s; } - - void handleLock(SAddr addr, ASize size, const EventDeps *deps); - void handleUnlock(SAddr addr, ASize size, const EventDeps *deps); - - /* Custom Opcode Implementations */ -#define DECLARE_CUSTOM_OPCODE(_name) \ - void call ## _name(Function *F, const std::vector &ArgVals, \ - const std::unique_ptr &specialDeps) - - DECLARE_CUSTOM_OPCODE(AssertFail); - DECLARE_CUSTOM_OPCODE(OptBegin); - DECLARE_CUSTOM_OPCODE(LoopBegin); - DECLARE_CUSTOM_OPCODE(RecAssertFail); - DECLARE_CUSTOM_OPCODE(SpinStart); - DECLARE_CUSTOM_OPCODE(SpinEnd); - DECLARE_CUSTOM_OPCODE(FaiZNESpinEnd); - DECLARE_CUSTOM_OPCODE(LockZNESpinEnd); - DECLARE_CUSTOM_OPCODE(KillThread); - DECLARE_CUSTOM_OPCODE(Assume); - DECLARE_CUSTOM_OPCODE(NondetInt); - DECLARE_CUSTOM_OPCODE(Malloc); - DECLARE_CUSTOM_OPCODE(MallocAligned); - DECLARE_CUSTOM_OPCODE(PMalloc); - DECLARE_CUSTOM_OPCODE(Free); - DECLARE_CUSTOM_OPCODE(ThreadSelf); - DECLARE_CUSTOM_OPCODE(ThreadCreate); - DECLARE_CUSTOM_OPCODE(ThreadCreateSymmetric); - DECLARE_CUSTOM_OPCODE(ThreadJoin); - DECLARE_CUSTOM_OPCODE(ThreadExit); - DECLARE_CUSTOM_OPCODE(AtExit); - DECLARE_CUSTOM_OPCODE(MutexInit); - DECLARE_CUSTOM_OPCODE(MutexLock); - DECLARE_CUSTOM_OPCODE(MutexUnlock); - DECLARE_CUSTOM_OPCODE(MutexTrylock); - DECLARE_CUSTOM_OPCODE(MutexDestroy); - DECLARE_CUSTOM_OPCODE(BarrierInit); - DECLARE_CUSTOM_OPCODE(BarrierWait); - DECLARE_CUSTOM_OPCODE(BarrierDestroy); - DECLARE_CUSTOM_OPCODE(HazptrAlloc); - DECLARE_CUSTOM_OPCODE(HazptrProtect); - DECLARE_CUSTOM_OPCODE(HazptrClear); - DECLARE_CUSTOM_OPCODE(HazptrFree); - DECLARE_CUSTOM_OPCODE(HazptrRetire); - DECLARE_CUSTOM_OPCODE(OpenFS); - DECLARE_CUSTOM_OPCODE(CreatFS); - DECLARE_CUSTOM_OPCODE(CloseFS); - DECLARE_CUSTOM_OPCODE(RenameFS); - DECLARE_CUSTOM_OPCODE(LinkFS); - DECLARE_CUSTOM_OPCODE(UnlinkFS); - DECLARE_CUSTOM_OPCODE(TruncateFS); - DECLARE_CUSTOM_OPCODE(ReadFS); - DECLARE_CUSTOM_OPCODE(WriteFS); - DECLARE_CUSTOM_OPCODE(SyncFS); - DECLARE_CUSTOM_OPCODE(FsyncFS); - DECLARE_CUSTOM_OPCODE(PreadFS); - DECLARE_CUSTOM_OPCODE(PwriteFS); - DECLARE_CUSTOM_OPCODE(LseekFS); - DECLARE_CUSTOM_OPCODE(PersBarrierFS); - DECLARE_CUSTOM_OPCODE(SmpFenceLKMM); - DECLARE_CUSTOM_OPCODE(RCUReadLockLKMM); - DECLARE_CUSTOM_OPCODE(RCUReadUnlockLKMM); - DECLARE_CUSTOM_OPCODE(SynchronizeRCULKMM); - DECLARE_CUSTOM_OPCODE(CLFlush); - - void callInternalFunction(Function *F, const std::vector &ArgVals, - const std::unique_ptr &deps); - - void freeAllocas(const AllocaHolder &allocas); - - /* Collects the addresses (and some naming information) for all variables with - * static storage. Also calculates the starting address of the allocation pool */ - void collectStaticAddresses(SAddrAllocator &alloctor); - - /* Sets up how some errors will be reported to the user */ - void setupErrorPolicy(Module *M, const Config *userConf); - - /* Pers: Sets up information about the modeled filesystem */ - void setupFsInfo(Module *M, const Config *userConf); - - /* Adds the specified thread to the list */ - Thread &addNewThread(Thread &&thread); - - /* Creates an entry for the main() function. More information are - * filled from the execution engine when the exploration starts */ - Thread &createAddMainThread(); - - /* Dependency tracking */ - - DepTracker *getDepTracker() { return &*dynState.depTracker; } - const DepTracker *getDepTracker() const { return &*dynState.depTracker; } - - std::unique_ptr - makeEventDeps(const DepInfo *addr, const DepInfo *data, - const DepInfo *ctrl, const DepInfo *addrPo, - const DepInfo *cas); - - const DepInfo *getDataDeps(unsigned int tid, Value *i) { - return getDepTracker() ? getDepTracker()->getDataDeps(tid, i) : nullptr; - } - const DepInfo *getAddrPoDeps(unsigned int tid) { - return getDepTracker() ? getDepTracker()->getAddrPoDeps(tid) : nullptr; - } - const DepInfo *getCtrlDeps(unsigned int tid) { - return getDepTracker() ? getDepTracker()->getCtrlDeps(tid) : nullptr; - } - - void updateDataDeps(unsigned int tid, Value *dst, Value *src) { - if (getDepTracker()) - getDepTracker()->updateDataDeps(tid, dst, src); - } - void updateDataDeps(unsigned int tid, Value *dst, const DepInfo *e) { - if (getDepTracker()) - getDepTracker()->updateDataDeps(tid, dst, *e); - } - void updateDataDeps(unsigned int tid, Value *dst, Event e) { - if (getDepTracker()) - getDepTracker()->updateDataDeps(tid, dst, e); - } - void updateAddrPoDeps(unsigned int tid, Value *src) { - if (getDepTracker()) - getDepTracker()->updateAddrPoDeps(tid, src); - } - void updateCtrlDeps(unsigned int tid, Value *src) { - if (getDepTracker()) - getDepTracker()->updateCtrlDeps(tid, src); - } - - std::unique_ptr updateFunArgDeps(unsigned int tid, Function *F); - void updateInternalFunRetDeps(unsigned int tid, Function *F, Instruction *CS); - - void clearDeps(unsigned int tid) { - if (getDepTracker()) - getDepTracker()->clearDeps(tid); - } - - /* Gets naming information for value V (or value with key KEY), if it is - * an internal variable with no value correspondence */ - const NameInfo *getVarNameInfo(Value *v, StorageDuration sd, AddressSpace spc, - const VariableInfo::InternalKey &key = {}); - - /* Pers: Returns the address of the file description referenced by FD */ - void *getFileFromFd(int fd) const; - - /* Pers: Tracks that the address of the file description of FD is FILEADDR */ - void setFdToFile(int fd, void *fileAddr); - - /* Pers: Directory operations */ - void *getDirInode() const; - void *getInodeAddrFromName(const std::string &filename) const; - -}; - -} // End llvm namespace - -#endif diff --git a/src/InterpreterEnumAPI.cpp b/src/InterpreterEnumAPI.cpp deleted file mode 100644 index 6e0cc26..0000000 --- a/src/InterpreterEnumAPI.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#include "InterpreterEnumAPI.hpp" -#include "Error.hpp" - -const std::unordered_map internalFunNames = { - {"__VERIFIER_assert_fail", InternalFunctions::FN_AssertFail}, - {"__VERIFIER_opt_begin", InternalFunctions::FN_OptBegin}, - {"__VERIFIER_loop_begin", InternalFunctions::FN_LoopBegin}, - {"__VERIFIER_spin_start", InternalFunctions::FN_SpinStart}, - {"__VERIFIER_spin_end", InternalFunctions::FN_SpinEnd}, - {"__VERIFIER_faiZNE_spin_end", InternalFunctions::FN_FaiZNESpinEnd}, - {"__VERIFIER_lockZNE_spin_end", InternalFunctions::FN_LockZNESpinEnd}, - {"__VERIFIER_kill_thread", InternalFunctions::FN_KillThread}, - {"__VERIFIER_assume", InternalFunctions::FN_Assume}, - {"__VERIFIER_nondet_int", InternalFunctions::FN_NondetInt}, - {"__VERIFIER_malloc", InternalFunctions::FN_Malloc}, - {"__VERIFIER_malloc_aligned", InternalFunctions::FN_MallocAligned}, - {"__VERIFIER_palloc", InternalFunctions::FN_PMalloc}, - {"__VERIFIER_free", InternalFunctions::FN_Free}, - {"__VERIFIER_thread_self", InternalFunctions::FN_ThreadSelf}, - {"__VERIFIER_thread_create", InternalFunctions::FN_ThreadCreate}, - {"__VERIFIER_thread_create_symmetric", InternalFunctions::FN_ThreadCreateSymmetric}, - {"__VERIFIER_thread_join", InternalFunctions::FN_ThreadJoin}, - {"__VERIFIER_thread_exit", InternalFunctions::FN_ThreadExit}, - {"__VERIFIER_atexit", InternalFunctions::FN_AtExit}, - {"__VERIFIER_mutex_init", InternalFunctions::FN_MutexInit}, - {"__VERIFIER_mutex_lock", InternalFunctions::FN_MutexLock}, - {"__VERIFIER_mutex_unlock", InternalFunctions::FN_MutexUnlock}, - {"__VERIFIER_mutex_trylock", InternalFunctions::FN_MutexTrylock}, - {"__VERIFIER_mutex_destroy", InternalFunctions::FN_MutexDestroy}, - {"__VERIFIER_barrier_init", InternalFunctions::FN_BarrierInit}, - {"__VERIFIER_barrier_wait", InternalFunctions::FN_BarrierWait}, - {"__VERIFIER_barrier_destroy", InternalFunctions::FN_BarrierDestroy}, - {"__VERIFIER_hazptr_alloc", InternalFunctions::FN_HazptrAlloc}, - {"__VERIFIER_hazptr_protect", InternalFunctions::FN_HazptrProtect}, - {"__VERIFIER_hazptr_clear", InternalFunctions::FN_HazptrClear}, - {"__VERIFIER_hazptr_free", InternalFunctions::FN_HazptrFree}, - {"__VERIFIER_hazptr_retire", InternalFunctions::FN_HazptrRetire}, - {"__VERIFIER_openFS", InternalFunctions::FN_OpenFS}, - {"__VERIFIER_closeFS", InternalFunctions::FN_CloseFS}, - {"__VERIFIER_creatFS", InternalFunctions::FN_CreatFS}, - {"__VERIFIER_renameFS", InternalFunctions::FN_RenameFS}, - {"__VERIFIER_linkFS", InternalFunctions::FN_LinkFS}, - {"__VERIFIER_unlinkFS", InternalFunctions::FN_UnlinkFS}, - {"__VERIFIER_truncateFS", InternalFunctions::FN_TruncateFS}, - {"__VERIFIER_readFS", InternalFunctions::FN_ReadFS}, - {"__VERIFIER_preadFS", InternalFunctions::FN_PreadFS}, - {"__VERIFIER_writeFS", InternalFunctions::FN_WriteFS}, - {"__VERIFIER_pwriteFS", InternalFunctions::FN_PwriteFS}, - {"__VERIFIER_fsyncFS", InternalFunctions::FN_FsyncFS}, - {"__VERIFIER_syncFS", InternalFunctions::FN_SyncFS}, - {"__VERIFIER_lseekFS", InternalFunctions::FN_LseekFS}, - {"__VERIFIER_pbarrier", InternalFunctions::FN_PersBarrierFS}, - {"__VERIFIER_annotate_begin", InternalFunctions::FN_AnnotateBegin}, - {"__VERIFIER_annotate_end", InternalFunctions::FN_AnnotateEnd}, - {"__VERIFIER_lkmm_fence", InternalFunctions::FN_SmpFenceLKMM}, - {"__VERIFIER_rcu_read_lock", InternalFunctions::FN_RCUReadLockLKMM}, - {"__VERIFIER_rcu_read_unlock", InternalFunctions::FN_RCUReadUnlockLKMM}, - {"__VERIFIER_synchronize_rcu", InternalFunctions::FN_SynchronizeRCULKMM}, - {"__VERIFIER_clflush", InternalFunctions::FN_CLFlush}, - /* Some C++ calls */ - {"_Znwm", InternalFunctions::FN_Malloc}, - {"_ZdlPv", InternalFunctions::FN_Free}, -}; diff --git a/src/IntrinsicLoweringPass.hpp b/src/IntrinsicLoweringPass.hpp deleted file mode 100644 index 9267d35..0000000 --- a/src/IntrinsicLoweringPass.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __INTRINSIC_LOWERING_PASS_HPP__ -#define __INTRINSIC_LOWERING_PASS_HPP__ - -#include -#include -#include -#include - -class IntrinsicLoweringPass : public llvm::ModulePass { - -public: - static char ID; - const llvm::DataLayout &dataLayout; - llvm::IntrinsicLowering *IL; - - IntrinsicLoweringPass(const llvm::DataLayout &TD) - : llvm::ModulePass(ID), dataLayout(TD), IL(new llvm::IntrinsicLowering(TD)) - {} - ~IntrinsicLoweringPass() { delete IL; } - virtual bool runOnModule(llvm::Module &M); - -protected: - bool runOnBasicBlock(llvm::BasicBlock &BB, llvm::Module &M); -}; - -#endif /* __INTRINSIC_LOWERING_PASS_HPP__ */ diff --git a/src/LLVMModule.cpp b/src/LLVMModule.cpp deleted file mode 100644 index b23da03..0000000 --- a/src/LLVMModule.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#include "config.h" - -#include "Error.hpp" -#include "LLVMModule.hpp" -#include "Passes.hpp" -#include "SExprVisitor.hpp" -#include -#if defined(HAVE_LLVM_BITCODE_READERWRITER_H) -#include -#else -#include -#include -#endif -#if defined(HAVE_LLVM_PASSMANAGER_H) -#include -#elif defined(HAVE_LLVM_IR_PASSMANAGER_H) -#include -#endif -#if defined(HAVE_LLVM_IR_LEGACYPASSMANAGER_H) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(HAVE_LLVM_TRANSFORMS_UTILS_H) -#include -#endif - -#define PassManager llvm::legacy::PassManager - -namespace LLVMModule { - -std::unique_ptr parseLLVMModule(const std::string &filename, - const std::unique_ptr &ctx) -{ - llvm::SMDiagnostic err; - - auto mod = llvm::parseIRFile(filename, err, *ctx); - if (!mod) { - err.print(filename.c_str(), llvm::dbgs()); - ERROR("Could not parse LLVM IR!\n"); - } - return std::move(mod); -} - -std::unique_ptr cloneModule(const std::unique_ptr &mod, - const std::unique_ptr &ctx) -{ - /* Roundtrip the module to a stream and then back into the new context */ - std::string str; - llvm::raw_string_ostream stream(str); - - llvm::WriteBitcodeToFile(*mod, stream); - - llvm::StringRef ref(stream.str()); - std::unique_ptr buf(llvm::MemoryBuffer::getMemBuffer(ref)); - - return std::move(llvm::parseBitcodeFile(buf->getMemBufferRef(), *ctx).get()); -} - -void initializeVariableInfo(ModuleInfo &MI, PassModuleInfo &PI) -{ - for (auto &kv : PI.varInfo.globalInfo) - MI.varInfo.globalInfo[MI.idInfo.VID.at(kv.first)] = kv.second; - for (auto &kv : PI.varInfo.localInfo) { - if (MI.idInfo.VID.count(kv.first)) - MI.varInfo.localInfo[MI.idInfo.VID.at(kv.first)] = kv.second; - } - MI.varInfo.internalInfo = PI.varInfo.internalInfo; - return; -} - -void initializeAnnotationInfo(ModuleInfo &MI, PassModuleInfo &PI) -{ - using Transformer = SExprTransformer; - Transformer tr; - - for (auto &kv : PI.annotInfo.annotMap) { - MI.annotInfo.annotMap[MI.idInfo.VID.at(kv.first)] = tr.transform( - &*kv.second, [&](llvm::Value *v) { return MI.idInfo.VID.at(v); }); - } -} - -void initializeFsInfo(ModuleInfo &MI, PassModuleInfo &PI) -{ - MI.fsInfo.filenames.insert(PI.filenames.begin(), PI.filenames.end()); - return; -} - -void initializeModuleInfo(ModuleInfo &MI, PassModuleInfo &PI) -{ - MI.collectIDs(); - initializeVariableInfo(MI, PI); - initializeAnnotationInfo(MI, PI); - initializeFsInfo(MI, PI); - MI.determinedMM = PI.determinedMM; - return; -} - -bool transformLLVMModule(llvm::Module &mod, ModuleInfo &MI, - const std::shared_ptr &conf) -{ - llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); - PassModuleInfo PI; - PassManager OptPM, BndPM; - bool modified; - - llvm::initializeCore(Registry); - llvm::initializeScalarOpts(Registry); - llvm::initializeVectorization(Registry); - llvm::initializeIPO(Registry); - llvm::initializeAnalysis(Registry); - llvm::initializeTransformUtils(Registry); - llvm::initializeInstCombine(Registry); - llvm::initializeTarget(Registry); -#if LLVM_VERSION_MAJOR < 16 - llvm::initializeObjCARCOpts(Registry); - llvm::initializeInstrumentation(Registry); -#endif - - OptPM.add(createDeclareInternalsPass()); - OptPM.add(createDefineLibcFunsPass()); - OptPM.add(createMDataCollectionPass(&PI)); - if (conf->inlineFunctions) - OptPM.add(createFunctionInlinerPass()); - OptPM.add(createPromoteMemIntrinsicPass()); - OptPM.add(createIntrinsicLoweringPass(mod)); - if (conf->castElimination) - OptPM.add(createEliminateCastsPass()); - OptPM.add(llvm::createPromoteMemoryToRegisterPass()); - OptPM.add(llvm::createDeadArgEliminationPass()); - OptPM.add(createLocalSimplifyCFGPass()); - OptPM.add(createEliminateAnnotationsPass()); - OptPM.add(createEliminateRedundantInstPass()); - if (conf->mmDetector) - OptPM.add(createMMDetectorPass(&PI)); - - modified = OptPM.run(mod); - - BndPM.add(createEliminateCASPHIsPass()); - BndPM.add(llvm::createJumpThreadingPass()); - BndPM.add(createEliminateUnusedCodePass()); - BndPM.add(createBisimilarityCheckerPass()); - if (conf->codeCondenser && !conf->checkLiveness) - BndPM.add(createCodeCondenserPass()); - if (conf->loopJumpThreading) - BndPM.add(createLoopJumpThreadingPass()); - BndPM.add(createCallInfoCollectionPass()); - BndPM.add(createEscapeCheckerPass()); - if (conf->spinAssume) - BndPM.add(createSpinAssumePass(conf->checkLiveness)); - if (conf->unroll.has_value()) - BndPM.add(createLoopUnrollPass(*conf->unroll, conf->noUnrollFuns)); - - modified |= BndPM.run(mod); - - /* Run annotation passes last so that the module is stable */ - if (conf->assumePropagation) - OptPM.add(createPropagateAssumesPass()); - if (conf->confirmAnnot) - OptPM.add(createConfirmationAnnotationPass()); - if (conf->loadAnnot) - OptPM.add(createLoadAnnotationPass(PI.annotInfo)); - modified |= OptPM.run(mod); - - initializeModuleInfo(MI, PI); - - assert(!llvm::verifyModule(mod, &llvm::dbgs())); - return modified; -} - -void printLLVMModule(llvm::Module &mod, const std::string &out) -{ - PassManager PM; - std::error_code errs; - - auto flags = -#if LLVM_VERSION_MAJOR < 13 - llvm::sys::fs::F_None; -#else - llvm::sys::fs::OF_None; -#endif - - auto os = std::make_unique(out.c_str(), errs, flags); - - /* TODO: Do we need an exception? If yes, properly handle it */ - if (errs) { - WARN("Failed to write transformed module to file " + out + ": " + errs.message()); - return; - } - - PM.add(llvm::createPrintModulePass(*os)); - PM.run(mod); - return; -} - -} // namespace LLVMModule diff --git a/src/LoadAnnotationPass.hpp b/src/LoadAnnotationPass.hpp deleted file mode 100644 index f7fb697..0000000 --- a/src/LoadAnnotationPass.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __LOAD_ANNOTATION_PASS_HPP__ -#define __LOAD_ANNOTATION_PASS_HPP__ - -#include "ModuleInfo.hpp" -#include -#include - -using namespace llvm; - -class LoadAnnotationPass : public FunctionPass { - -public: - static char ID; - AnnotationInfo &LAI; - - LoadAnnotationPass(AnnotationInfo &LAI) - : FunctionPass(ID), LAI(LAI){}; - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &F); - -private: - /* - * Returns the source loads of an assume statement, that is, - * loads the result of which is used in the assume. - */ - std::vector getSourceLoads(CallInst *assm) const; - - /* - * Given an assume's source loads, returns the annotatable ones. - */ - std::vector - filterAnnotatableFromSource(CallInst *assm, const std::vector &source) const; - - /* - * Returns all of ASSM's annotatable loads - */ - std::vector getAnnotatableLoads(CallInst *assm) const; -}; - -#endif /* __LOAD_ANNOTATION_PASS_HPP__ */ diff --git a/src/LocalSimplifyCFGPass.hpp b/src/LocalSimplifyCFGPass.hpp deleted file mode 100644 index 77caab9..0000000 --- a/src/LocalSimplifyCFGPass.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __LOCAL_SIMPLIFY_CFG_PASS_HPP__ -#define __LOCAL_SIMPLIFY_CFG_PASS_HPP__ - -#include - -class LocalSimplifyCFGPass : public llvm::FunctionPass { - -public: - static char ID; - - LocalSimplifyCFGPass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; -}; - -#endif /* __LOCAL_SIMPLIFY_CFG_PASS_HPP__ */ diff --git a/src/LoopJumpThreadingPass.hpp b/src/LoopJumpThreadingPass.hpp deleted file mode 100644 index 3c71361..0000000 --- a/src/LoopJumpThreadingPass.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __LOOP_THREAD_JUMPING_PASS_HPP__ -#define __LOOP_THREAD_JUMPING_PASS_HPP__ - -#include "config.h" - -#include -#ifdef LLVM_PASS_GETPASSNAME_IS_STRINGREF -#include -#endif -#include - -class LoopJumpThreadingPass : public llvm::LoopPass { - -public: - static char ID; - - LoopJumpThreadingPass() : llvm::LoopPass(ID) {} - -protected: - virtual llvm::StringRef getPassName() const { return "LoopJumpThreadingPass"; } - virtual void getAnalysisUsage(llvm::AnalysisUsage &au) const; - virtual bool runOnLoop(llvm::Loop *l, llvm::LPPassManager &LPM); -}; - -#endif /* __LOOP_THREAD_JUMPING_PASS_HPP__ */ diff --git a/src/MDataCollectionPass.cpp b/src/MDataCollectionPass.cpp deleted file mode 100644 index 2e91b42..0000000 --- a/src/MDataCollectionPass.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#include "MDataCollectionPass.hpp" -#include "CallInstWrapper.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace llvm; - -void MDataCollectionPass::getAnalysisUsage(llvm::AnalysisUsage &au) const { au.setPreservesAll(); } - -void MDataCollectionPass::collectVarName(Module &M, unsigned int ptr, Type *typ, DIType *dit, - std::string nameBuilder, NameInfo &info) -{ - if (!isa(typ) && !isa(typ) && !isa(typ)) { - info.addOffsetInfo(ptr, nameBuilder); - return; - } - - unsigned int offset = 0; - if (ArrayType *AT = dyn_cast(typ)) { - auto *newDit = dit; - if (auto *dict = dyn_cast(dit)) { - newDit = (!dict->getBaseType()) - ? dict - : llvm::dyn_cast(dict->getBaseType()); - } - auto elemSize = M.getDataLayout().getTypeAllocSize(AT->getElementType()); - for (auto i = 0u; i < AT->getNumElements(); i++) { - collectVarName(M, ptr + offset, AT->getElementType(), newDit, - nameBuilder + "[" + std::to_string(i) + "]", info); - offset += elemSize; - } - } else if (StructType *ST = dyn_cast(typ)) { - DINodeArray dictElems; - - /* Since this is a struct type, the metadata should yield a - * composite type, or a derived type that will eventually - * yield a composite type. */ - if (auto *dict = dyn_cast(dit)) { - dictElems = dict->getElements(); - } - if (auto *dict = dyn_cast(dit)) { - DIType *dbt = dict; - while (auto *dbtc = dyn_cast(dbt)) - dbt = dyn_cast(dbtc->getBaseType()); - - if (auto *dbtc = dyn_cast(dbt)) - dictElems = dbtc->getElements(); - else { - /* Take some precautions, in case we got this - * metadata thing all wrong... */ - PRINT_BUGREPORT_INFO_ONCE("struct-mdata", - "Cannot get variable naming info"); - return; - } - } - - /* It can be dictElems.size() < ST->getNumElements(), e.g., for va_arg */ - auto i = 0u; - auto minSize = std::min(dictElems.size(), ST->getNumElements()); - for (auto it = ST->element_begin(); i < minSize; ++it, ++i) { - auto elemSize = M.getDataLayout().getTypeAllocSize(*it); - auto didt = dictElems[i]; - if (auto *dit = dyn_cast(didt)) { - if (auto ditb = dyn_cast(dit->getBaseType())) - collectVarName(M, ptr + offset, *it, ditb, - nameBuilder + "." + dit->getName().str(), - info); - } - offset += elemSize; - } - } else { - BUG(); - } - return; -} - -void MDataCollectionPass::collectGlobalInfo(GlobalVariable &v, Module &M) -{ - /* If we already have data for the variable, skip */ - if (hasGlobalInfo(&v)) - return; - - auto &info = getGlobalInfo(&v); - info = std::make_shared(); - - if (!v.getMetadata("dbg")) - return; - - BUG_ON(!isa(v.getMetadata("dbg"))); - auto *dive = static_cast(v.getMetadata("dbg")); - auto dit = dive->getVariable()->getType(); - - /* Check whether it is a global pointer */ - if (auto ditc = dyn_cast(dit)) - collectVarName(M, 0, v.getValueType(), ditc, "", *info); - return; -} - -void MDataCollectionPass::collectLocalInfo(DbgDeclareInst *DD, Module &M) -{ - /* Skip if it's not an alloca or we don't have data */ - auto *v = dyn_cast(DD->getAddress()); - if (!v) - return; - - if (hasLocalInfo(v)) - return; - - auto &info = getLocalInfo(v); - info = std::make_shared(); - - /* Store alloca's metadata, in case it's used in memcpy */ - allocaMData[v] = DD->getVariable(); - - auto dit = DD->getVariable()->getType(); - if (auto ditc = dyn_cast(dit)) - collectVarName(M, 0, v->getAllocatedType(), ditc, "", *info); - return; -} - -void MDataCollectionPass::collectMemCpyInfo(MemCpyInst *mi, Module &M) -{ - /* - * Only mark global variables w/ private linkage that will - * otherwise go undetected by this pass - */ - auto *src = dyn_cast(mi->getSource()); - if (!src) - return; - - if (hasGlobalInfo(src)) - return; - - auto &info = getGlobalInfo(src); - info = std::make_shared(); - - /* - * Since there will be no metadata for variables with private linkage, - * we do a small hack and take the metadata of memcpy()'s dest for - * memcpy()'s source - * The type of the dest is guaranteed to be a pointer - */ - auto *dst = dyn_cast(mi->getDest()); - BUG_ON(!dst); - - if (allocaMData.count(dst) == 0) - return; /* We did our best, but couldn't get a name for it... */ - auto dit = allocaMData[dst]->getType(); - if (auto ditc = dyn_cast(dit)) - collectVarName(M, 0, dst->getAllocatedType(), ditc, "", *info); - return; -} - -/* We need to take special care so that these internal types - * actually match the ones used by the ExecutionEngine */ -void MDataCollectionPass::collectInternalInfo(Module &M) -{ - /* We need to find out the size of an integer and the size of a pointer - * in this platform. HACK: since all types can be safely converted to - * void *, we take the size of a void * to see how many bytes are - * necessary to represent a pointer, and get the integer type from - * main()'s return type... */ - auto *main = M.getFunction("main"); - if (!main || !main->getReturnType()->isIntegerTy()) { - WARN_ONCE("internal-mdata", - "Could not get " - "naming info for internal variable. " - "(Does main() return int?)\n" - "Please submit a bug report to " PACKAGE_BUGREPORT "\n"); - return; - } - - auto &DL = M.getDataLayout(); - auto *intTyp = main->getReturnType(); - auto intByteWidth = DL.getTypeAllocSize(intTyp); - - auto *intPtrTyp = intTyp->getPointerTo(); - auto intPtrByteWidth = DL.getTypeAllocSize(intPtrTyp); - - /* struct file */ - auto offset = 0u; - auto &fileInfo = getInternalInfo("file"); - fileInfo = std::make_shared(); - - fileInfo->addOffsetInfo(offset, ".inode"); - fileInfo->addOffsetInfo((offset += intPtrByteWidth), ".count"); - fileInfo->addOffsetInfo((offset += intByteWidth), ".flags"); - fileInfo->addOffsetInfo((offset += intByteWidth), ".pos_lock"); - fileInfo->addOffsetInfo((offset += intByteWidth), ".pos"); - - /* struct inode */ - offset = 0; - auto &inodeInfo = getInternalInfo("inode"); - inodeInfo = std::make_shared(); - - inodeInfo->addOffsetInfo(offset, ".lock"); - inodeInfo->addOffsetInfo((offset += intByteWidth), ".i_size"); - inodeInfo->addOffsetInfo((offset += intByteWidth), ".i_transaction"); - inodeInfo->addOffsetInfo((offset += intByteWidth), ".i_disksize"); - inodeInfo->addOffsetInfo((offset += intByteWidth), ".data"); - return; -} - -bool isSyscallWPathname(CallInst *CI) -{ - /* Use getCalledValue() to deal with indirect invocations too */ - auto name = getCalledFunOrStripValName(*CI); - if (!isInternalFunction(name)) - return false; - - auto icode = internalFunNames.at(name); - return isFsInodeCode(icode); -} - -void MDataCollectionPass::initializeFilenameEntry(Value *v) -{ -#if LLVM_VERSION_MAJOR < 15 - if (auto *CE = dyn_cast(v)) { - auto filename = - dyn_cast( - dyn_cast(CE->getOperand(0))->getInitializer()) - ->getAsCString() - .str(); -#else - if (auto *CE = dyn_cast(v)) { - auto filename = - dyn_cast(CE->getOperand(0))->getAsCString().str(); -#endif - collectFilename(filename); - } else - ERROR("Non-constant expression in filename\n"); - return; -} - -void MDataCollectionPass::collectFilenameInfo(CallInst *CI, Module &M) -{ - auto *F = CI->getCalledFunction(); - auto ai = CI->arg_begin(); - - /* Fetch the first argument of the syscall as a string. - * We simply initialize the entries in the map; they will be - * populated with actual addresses from the EE */ - initializeFilenameEntry(CI->getArgOperand(0)); - - /* For some syscalls we capture the second argument as well */ - auto fCode = internalFunNames.at(F->getName().str()); - if (fCode == InternalFunctions::FN_RenameFS || fCode == InternalFunctions::FN_LinkFS) { - initializeFilenameEntry(CI->getArgOperand(1)); - } - return; -} - -bool MDataCollectionPass::runOnModule(Module &M) -{ - if (!PI) - return false; - - /* First, get type information for user's global variables */ - for (auto &v : M.getGlobalList()) - collectGlobalInfo(v, M); - - /* Then for all local variables and some other special cases */ - for (auto &F : M) { - for (auto it = inst_iterator(F), ei = inst_end(F); it != ei; ++it) { - if (auto *dd = dyn_cast(&*it)) - collectLocalInfo(dd, M); - if (auto *mi = dyn_cast(&*it)) - collectMemCpyInfo(mi, M); - if (auto *ci = dyn_cast(&*it)) { - if (isSyscallWPathname(ci)) - collectFilenameInfo(ci, M); - } - } - } - - /* Finally, collect internal type information */ - collectInternalInfo(M); - return false; -} - -ModulePass *createMDataCollectionPass(PassModuleInfo *PI) -{ - auto *P = new MDataCollectionPass(); - P->setPassModuleInfo(PI); - return P; -} - -char MDataCollectionPass::ID = 42; -static llvm::RegisterPass P("mdata-collection", - "Collections various metadata of a module."); diff --git a/src/Passes.hpp b/src/Passes.hpp deleted file mode 100644 index ffc1a75..0000000 --- a/src/Passes.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __PASSES_HPP__ -#define __PASSES_HPP__ - -#include "VSet.hpp" -#include "config.h" -#include -#include - -template struct AnnotationInfo; -struct PassModuleInfo; -struct ModuleInfo; - -/* - * Finds all bisimilarity pairs in a function. - */ -llvm::FunctionPass *createBisimilarityCheckerPass(); - -/* - * Collects function call information (e.g., whether a function has side effects) - * in a given module. - */ -llvm::ModulePass *createCallInfoCollectionPass(); - -/* - * Condenses the code by merging bisimilar points. - */ -llvm::FunctionPass *createCodeCondenserPass(); - -/* - * Declares GenMC functions. - */ -llvm::ModulePass *createDeclareInternalsPass(); - -/* - * Defines some commonly used libc functions (currently replaces then with no-ops). - */ -llvm::ModulePass *createDefineLibcFunsPass(); - -/* - * Lowers intrinsic calls. - */ -llvm::ModulePass *createIntrinsicLoweringPass(llvm::Module &M); - -/* - * Collects annotation information for a function's load instructions. - */ -llvm::FunctionPass * -createLoadAnnotationPass(AnnotationInfo &AI); - -/* - * Unrolls a loop N times, unless the loop is in a function present in NOUNROLLFUNS - */ -llvm::Pass *createLoopUnrollPass(unsigned int depth, const VSet &noUnrollFuns = {}); - -/* - * Performs jump-threading for some simple classes of loops. - */ -llvm::Pass *createLoopJumpThreadingPass(); - -/* - * Collects naming information about a module's variables and fs calls. - * Makes sure the module information is up-to-date before doing so. - */ -llvm::ModulePass *createMDataCollectionPass(PassModuleInfo *PI); - -/* - * Promotes memcpy() and memset() calls to a series of loads and stores. - */ -llvm::ModulePass *createPromoteMemIntrinsicPass(); - -/* - * Transforms certain classes of spinloops to assume() statements. - */ -llvm::Pass *createSpinAssumePass(bool markStarts = false); - -/* - * Eliminates certain form of PHIs stemming from CASes - */ -llvm::Pass *createEliminateCASPHIsPass(); - -/* - * Eliminates certain form of casts - */ -llvm::Pass *createEliminateCastsPass(); - -/* - * Eliminates GenMC's internal annotations - */ -llvm::Pass *createEliminateAnnotationsPass(); - -/* - * Eliminates some unused code that does not affect the verification result - */ -llvm::Pass *createEliminateUnusedCodePass(); - -/* - * Collects possible escape points for a given function - */ -llvm::Pass *createEscapeCheckerPass(bool loadsEscape = true); - -/* - * Annotates confirming reads - */ -llvm::FunctionPass *createConfirmationAnnotationPass(); - -/* - * Propagates assume(0)s upwards. - */ -llvm::Pass *createPropagateAssumesPass(); - -/* - * Performs some minor simplifications to the CFG - */ -llvm::Pass *createLocalSimplifyCFGPass(); - -/* - * Eliminates redundant instructions - */ -llvm::Pass *createEliminateRedundantInstPass(); - -/* - * Inlines all functions of a module - */ -llvm::ModulePass *createFunctionInlinerPass(); - -/* - * Checks whether the memory model of a module can be inferred, - * and populates accordingly the module information - */ -llvm::ModulePass *createMMDetectorPass(PassModuleInfo *PI); - -#endif /* __PASSES_HPP__ */ diff --git a/src/PromoteMemIntrinsicPass.hpp b/src/PromoteMemIntrinsicPass.hpp deleted file mode 100644 index fcc4e1b..0000000 --- a/src/PromoteMemIntrinsicPass.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __PROMOTE_MEMINTRINSIC_PASS_HPP__ -#define __PROMOTE_MEMINTRINSIC_PASS_HPP__ - -#include -#include -#include -#include - -class PromoteMemIntrinsicPass : public llvm::ModulePass { - -public: - static char ID; - - PromoteMemIntrinsicPass() : llvm::ModulePass(ID), hasPromoted(false) {} - - virtual bool runOnModule(llvm::Module &M); - - void getAnalysisUsage(llvm::AnalysisUsage &au) const; - -protected: - /* Promoters for specific intrinsics */ - bool tryPromoteMemCpy(llvm::MemCpyInst *MI, llvm::Module &M); - bool tryPromoteMemSet(llvm::MemSetInst *MS, llvm::Module &M); - - /* Called to remove promoted intrinsics from the code */ - void removePromoted(); - - /* Intrinsics we need to promote to load/store pairs */ - llvm::SmallVector promoted; - - /* Whether we have promoted all intrinsics */ - bool hasPromoted; -}; - -#endif /* __PROMOTE_MEMINTRINSIC_PASS_HPP__ */ diff --git a/src/RADriver.cpp b/src/RADriver.cpp deleted file mode 100644 index a32d477..0000000 --- a/src/RADriver.cpp +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "RADriver.hpp" -#include "ModuleInfo.hpp" - -RADriver::RADriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) - : GenMCDriver(conf, std::move(mod), std::move(MI), mode) -{} - -void RADriver::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_3(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_3[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_4(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - visitedCalc0_4[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_5(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_4(pLab, calcRes); - } - visitedCalc0_5[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc0_6(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_3(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_6(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc0_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_5(pLab, calcRes); - } - visitedCalc0_6[lab->getStamp().get()] = NodeStatus::left; -} - -View RADriver::calculate0(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_3.clear(); - visitedCalc0_3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_4.clear(); - visitedCalc0_4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_5.clear(); - visitedCalc0_5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_6.clear(); - visitedCalc0_6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -void RADriver::visitCalc1_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc1_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_0(pLab, calcRes); - } - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitCalc1_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::left; -} - -View RADriver::calculate1(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc1_0.clear(); - visitedCalc1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_1.clear(); - visitedCalc1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_2.clear(); - visitedCalc1_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc1_1(lab, calcRes); - return calcRes; -} -std::vector> RADriver::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector RADriver::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - views.push_back(calculate1(lab)); - return std::move(views); -} - -void RADriver::updateMMViews(EventLabel *lab) -{ - lab->setCalculated(calculateSaved(lab)); - lab->setViews(calculateViews(lab)); - lab->setPrefixView(calculatePrefixView(lab)); -} - -bool RADriver::isDepTracking() const { return 0; } - -bool RADriver::visitInclusionLHS0_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab0 = lab; - return false; - } - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS0_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS0_0(pLab, v)) - return false; - } - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::checkInclusion0(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS0_0.clear(); - visitedInclusionLHS0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS0_1.clear(); - visitedInclusionLHS0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS0_1(lab, v); -} - -void RADriver::visitInclusionLHS1_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept1[lab->getStamp().get()] = true; - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitInclusionLHS1_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::left; -} - -bool RADriver::checkInclusion1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0.clear(); - visitedInclusionLHS1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS1_1.clear(); - visitedInclusionLHS1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept1.clear(); - lhsAccept1.resize(g.getMaxStamp().get() + 1, false); - rhsAccept1.clear(); - rhsAccept1.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS1_1(lab); - for (auto i = 0u; i < lhsAccept1.size(); i++) { - if (lhsAccept1[i] && !rhsAccept1[i]) { - racyLab1 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RADriver::visitInclusionLHS2_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab2 = lab; - return false; - } - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS2_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS2_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_1(pLab, v)) - return false; - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::checkInclusion2(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS2_0.clear(); - visitedInclusionLHS2_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_1.clear(); - visitedInclusionLHS2_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_2.clear(); - visitedInclusionLHS2_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS2_2(lab, v); -} - -void RADriver::visitInclusionLHS3_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept3[lab->getStamp().get()] = true; - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitInclusionLHS3_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { - auto status = visitedInclusionLHS3_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_0(pLab); - } - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitInclusionLHS3_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS3_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_1(pLab); - } - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool RADriver::checkInclusion3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0.clear(); - visitedInclusionLHS3_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_1.clear(); - visitedInclusionLHS3_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_2.clear(); - visitedInclusionLHS3_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept3.clear(); - lhsAccept3.resize(g.getMaxStamp().get() + 1, false); - rhsAccept3.clear(); - rhsAccept3.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS3_2(lab); - for (auto i = 0u; i < lhsAccept3.size(); i++) { - if (lhsAccept3[i] && !rhsAccept3[i]) { - racyLab3 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RADriver::visitInclusionLHS4_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab4 = lab; - return false; - } - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS4_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS4_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS4_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_1(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::checkInclusion4(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS4_0.clear(); - visitedInclusionLHS4_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_1.clear(); - visitedInclusionLHS4_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_2.clear(); - visitedInclusionLHS4_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS4_2(lab, v); -} - -void RADriver::visitInclusionLHS5_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept5[lab->getStamp().get()] = true; - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitInclusionLHS5_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedInclusionLHS5_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_0(pLab); - } - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RADriver::visitInclusionLHS5_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && - llvm::dyn_cast(lab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(lab))) - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS5_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_1(pLab); - } - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool RADriver::checkInclusion5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0.clear(); - visitedInclusionLHS5_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_1.clear(); - visitedInclusionLHS5_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_2.clear(); - visitedInclusionLHS5_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept5.clear(); - lhsAccept5.resize(g.getMaxStamp().get() + 1, false); - rhsAccept5.clear(); - rhsAccept5.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS5_2(lab); - for (auto i = 0u; i < lhsAccept5.size(); i++) { - if (lhsAccept5[i] && !rhsAccept5[i]) { - racyLab5 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RADriver::visitInclusionLHS6_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab6 = lab; - return false; - } - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS6_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::checkInclusion6(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS6_0.clear(); - visitedInclusionLHS6_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS6_1.clear(); - visitedInclusionLHS6_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS6_1(lab, v); -} - -bool RADriver::visitInclusionLHS7_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab7 = lab; - return false; - } - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::visitInclusionLHS7_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS7_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS7_0(pLab, v)) - return false; - } - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RADriver::checkInclusion7(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS7_0.clear(); - visitedInclusionLHS7_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS7_1.clear(); - visitedInclusionLHS7_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS7_1(lab, v); -} - -VerificationError RADriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const -{ - if (!checkInclusion0(lab)) { - race = racyLab0; - return VerificationError::VE_AccessNonMalloc; - } - - if (!checkInclusion1(lab)) { - race = racyLab1; - return VerificationError::VE_DoubleFree; - } - - if (!checkInclusion2(lab)) { - race = racyLab2; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion3(lab)) { - race = racyLab3; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion4(lab)) { - race = racyLab4; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion5(lab)) { - race = racyLab5; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion6(lab)) { - race = racyLab6; - return VerificationError::VE_RaceNotAtomic; - } - - return VerificationError::VE_OK; -} - -std::vector -RADriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const -{ - std::vector result; - - if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkInclusion7(lab)) { - racyLabs.push_back(racyLab7); - result.push_back(VerificationError::VE_WWRace); - } - - return result; -} - -bool RADriver::isConsistent(const EventLabel *lab) const { return true; } - -bool RADriver::isRecAcyclic(const EventLabel *lab) const -{ - visitedRecAccepting = 0; - return true; -} - -bool RADriver::isRecoveryValid(const EventLabel *lab) const { return isRecAcyclic(lab); } - -View RADriver::calcPPoRfBefore(const EventLabel *lab) const -{ - auto &g = getGraph(); - View pporf; - pporf.updateIdx(lab->getPos()); - - auto *pLab = g.getPreviousLabel(lab); - if (!pLab) - return pporf; - pporf.update(pLab->getPrefixView()); - if (auto *rLab = llvm::dyn_cast(pLab)) - pporf.update(rLab->getRf()->getPrefixView()); - if (auto *tsLab = llvm::dyn_cast(pLab)) - pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); - if (auto *tjLab = llvm::dyn_cast(pLab)) - pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); - return pporf; -} -std::unique_ptr RADriver::calculatePrefixView(const EventLabel *lab) const -{ - return std::make_unique(calcPPoRfBefore(lab)); -} - -const View &RADriver::getHbView(const EventLabel *lab) const { return lab->view(0); } - -bool RADriver::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(0); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector RADriver::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto &lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(&lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool RADriver::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(0).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(0).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator RADriver::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator RADriver::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(0).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(0).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator RADriver::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector RADriver::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInit()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector RADriver::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - std::vector rfAfter; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - return after; -} - -std::vector RADriver::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector RADriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(0); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(0).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(0).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -RADriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/RADriver.hpp b/src/RADriver.hpp deleted file mode 100644 index 335b40b..0000000 --- a/src/RADriver.hpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#ifndef __RA_DRIVER_HPP__ -#define __RA_DRIVER_HPP__ - -#include "ExecutionGraph.hpp" -#include "GenMCDriver.hpp" -#include "GraphIterators.hpp" -#include "MaximalIterator.hpp" -#include "VSet.hpp" -#include "VerificationError.hpp" -#include "config.h" -#include -#include - -class RADriver : public GenMCDriver { - -private: - enum class NodeStatus : unsigned char { unseen, entered, left }; - - struct NodeCountStatus { - NodeCountStatus() = default; - NodeCountStatus(uint16_t c, NodeStatus s) : count(c), status(s) {} - uint16_t count = 0; - NodeStatus status = NodeStatus::unseen; - }; - -public: - RADriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); - - std::vector> calculateSaved(const EventLabel *lab); - std::vector calculateViews(const EventLabel *lab); - void updateMMViews(EventLabel *lab) override; - bool isDepTracking() const override; - bool isConsistent(const EventLabel *lab) const override; - VerificationError checkErrors(const EventLabel *lab, - const EventLabel *&race) const override; - std::vector - checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const; - bool isRecoveryValid(const EventLabel *lab) const override; - std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; - const View &getHbView(const EventLabel *lab) const override; - std::vector getCoherentStores(SAddr addr, Event read) override; - std::vector getCoherentRevisits(const WriteLabel *sLab, - const VectorClock &pporf) override; - llvm::iterator_range - getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; - -private: - bool isWriteRfBefore(Event a, Event b); - std::vector getInitRfsAtLoc(SAddr addr); - bool isHbOptRfBefore(const Event e, const Event write); - ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); - ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); - ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); - std::vector getMOOptRfAfter(const WriteLabel *sLab); - std::vector getMOInvOptRfAfter(const WriteLabel *sLab); - - void visitCalc0_0(const EventLabel *lab, View &calcRes); - void visitCalc0_1(const EventLabel *lab, View &calcRes); - void visitCalc0_2(const EventLabel *lab, View &calcRes); - void visitCalc0_3(const EventLabel *lab, View &calcRes); - void visitCalc0_4(const EventLabel *lab, View &calcRes); - void visitCalc0_5(const EventLabel *lab, View &calcRes); - void visitCalc0_6(const EventLabel *lab, View &calcRes); - - View calculate0(const EventLabel *lab); - - mutable std::vector visitedCalc0_0; - mutable std::vector visitedCalc0_1; - mutable std::vector visitedCalc0_2; - mutable std::vector visitedCalc0_3; - mutable std::vector visitedCalc0_4; - mutable std::vector visitedCalc0_5; - mutable std::vector visitedCalc0_6; - - void visitCalc1_0(const EventLabel *lab, View &calcRes); - void visitCalc1_1(const EventLabel *lab, View &calcRes); - void visitCalc1_2(const EventLabel *lab, View &calcRes); - - View calculate1(const EventLabel *lab); - - mutable std::vector visitedCalc1_0; - mutable std::vector visitedCalc1_1; - mutable std::vector visitedCalc1_2; - - bool visitInclusionLHS0_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS0_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion0(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS0_0; - mutable std::vector visitedInclusionLHS0_1; - mutable std::vector visitedInclusionRHS0_0; - mutable std::vector visitedInclusionRHS0_1; - - mutable std::vector lhsAccept0; - mutable std::vector rhsAccept0; - - mutable const EventLabel *racyLab0 = nullptr; - - void visitInclusionLHS1_0(const EventLabel *lab) const; - void visitInclusionLHS1_1(const EventLabel *lab) const; - - bool checkInclusion1(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS1_0; - mutable std::vector visitedInclusionLHS1_1; - - mutable std::vector lhsAccept1; - mutable std::vector rhsAccept1; - - mutable const EventLabel *racyLab1 = nullptr; - - bool visitInclusionLHS2_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion2(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS2_0; - mutable std::vector visitedInclusionLHS2_1; - mutable std::vector visitedInclusionLHS2_2; - mutable std::vector visitedInclusionRHS2_0; - mutable std::vector visitedInclusionRHS2_1; - - mutable std::vector lhsAccept2; - mutable std::vector rhsAccept2; - - mutable const EventLabel *racyLab2 = nullptr; - - void visitInclusionLHS3_0(const EventLabel *lab) const; - void visitInclusionLHS3_1(const EventLabel *lab) const; - void visitInclusionLHS3_2(const EventLabel *lab) const; - - bool checkInclusion3(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS3_0; - mutable std::vector visitedInclusionLHS3_1; - mutable std::vector visitedInclusionLHS3_2; - - mutable std::vector lhsAccept3; - mutable std::vector rhsAccept3; - - mutable const EventLabel *racyLab3 = nullptr; - - bool visitInclusionLHS4_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion4(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS4_0; - mutable std::vector visitedInclusionLHS4_1; - mutable std::vector visitedInclusionLHS4_2; - mutable std::vector visitedInclusionRHS4_0; - mutable std::vector visitedInclusionRHS4_1; - - mutable std::vector lhsAccept4; - mutable std::vector rhsAccept4; - - mutable const EventLabel *racyLab4 = nullptr; - - void visitInclusionLHS5_0(const EventLabel *lab) const; - void visitInclusionLHS5_1(const EventLabel *lab) const; - void visitInclusionLHS5_2(const EventLabel *lab) const; - - bool checkInclusion5(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS5_0; - mutable std::vector visitedInclusionLHS5_1; - mutable std::vector visitedInclusionLHS5_2; - - mutable std::vector lhsAccept5; - mutable std::vector rhsAccept5; - - mutable const EventLabel *racyLab5 = nullptr; - - bool visitInclusionLHS6_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS6_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion6(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS6_0; - mutable std::vector visitedInclusionLHS6_1; - mutable std::vector visitedInclusionRHS6_0; - mutable std::vector visitedInclusionRHS6_1; - - mutable std::vector lhsAccept6; - mutable std::vector rhsAccept6; - - mutable const EventLabel *racyLab6 = nullptr; - - bool visitInclusionLHS7_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS7_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion7(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS7_0; - mutable std::vector visitedInclusionLHS7_1; - mutable std::vector visitedInclusionRHS7_0; - mutable std::vector visitedInclusionRHS7_1; - - mutable std::vector lhsAccept7; - mutable std::vector rhsAccept7; - - mutable const EventLabel *racyLab7 = nullptr; - - bool isRecAcyclic(const EventLabel *lab) const; - - mutable uint16_t visitedRecAccepting = 0; - void visitPPoRf0(const EventLabel *lab, View &pporf) const; - - View calcPPoRfBefore(const EventLabel *lab) const; - - mutable std::vector visitedPPoRf0; - - mutable std::vector> saved; - mutable std::vector views; -}; - -#endif /* __RA_DRIVER_HPP__ */ diff --git a/src/RC11Driver.cpp b/src/RC11Driver.cpp deleted file mode 100644 index 2c2ec6f..0000000 --- a/src/RC11Driver.cpp +++ /dev/null @@ -1,2195 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "RC11Driver.hpp" -#include "ModuleInfo.hpp" - -RC11Driver::RC11Driver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) - : GenMCDriver(conf, std::move(mod), std::move(MI), mode) -{} - -void RC11Driver::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -View RC11Driver::calculate0(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -void RC11Driver::visitCalc1_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_6(pLab, calcRes); - } - if (true && lab->isAtLeastAcquire() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_6(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto status = visitedCalc1_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_4(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_0(pLab, calcRes); - } - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_3(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_3[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_3(pLab, calcRes); - } - visitedCalc1_3[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_4(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_4[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_3(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc1_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_5(pLab, calcRes); - } - visitedCalc1_4[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_5(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_5[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc1_4[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_4(pLab, calcRes); - } - visitedCalc1_5[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitCalc1_6(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_6[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_6[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_6(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_3[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_3(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto status = visitedCalc1_5[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_5(pLab, calcRes); - } - visitedCalc1_6[lab->getStamp().get()] = NodeStatus::left; -} - -View RC11Driver::calculate1(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc1_0.clear(); - visitedCalc1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_1.clear(); - visitedCalc1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_2.clear(); - visitedCalc1_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_3.clear(); - visitedCalc1_3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_4.clear(); - visitedCalc1_4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_5.clear(); - visitedCalc1_5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_6.clear(); - visitedCalc1_6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc1_1(lab, calcRes); - return calcRes; -} -std::vector> RC11Driver::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector RC11Driver::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - views.push_back(calculate1(lab)); - return std::move(views); -} - -void RC11Driver::updateMMViews(EventLabel *lab) -{ - lab->setCalculated(calculateSaved(lab)); - lab->setViews(calculateViews(lab)); - lab->setPrefixView(calculatePrefixView(lab)); -} - -bool RC11Driver::isDepTracking() const { return 0; } - -bool RC11Driver::visitInclusionLHS0_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab0 = lab; - return false; - } - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS0_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS0_0(pLab, v)) - return false; - } - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::checkInclusion0(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS0_0.clear(); - visitedInclusionLHS0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS0_1.clear(); - visitedInclusionLHS0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS0_1(lab, v); -} - -void RC11Driver::visitInclusionLHS1_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept1[lab->getStamp().get()] = true; - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitInclusionLHS1_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::left; -} - -bool RC11Driver::checkInclusion1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0.clear(); - visitedInclusionLHS1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS1_1.clear(); - visitedInclusionLHS1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept1.clear(); - lhsAccept1.resize(g.getMaxStamp().get() + 1, false); - rhsAccept1.clear(); - rhsAccept1.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS1_1(lab); - for (auto i = 0u; i < lhsAccept1.size(); i++) { - if (lhsAccept1[i] && !rhsAccept1[i]) { - racyLab1 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RC11Driver::visitInclusionLHS2_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab2 = lab; - return false; - } - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS2_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS2_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_1(pLab, v)) - return false; - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::checkInclusion2(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS2_0.clear(); - visitedInclusionLHS2_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_1.clear(); - visitedInclusionLHS2_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_2.clear(); - visitedInclusionLHS2_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS2_2(lab, v); -} - -void RC11Driver::visitInclusionLHS3_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept3[lab->getStamp().get()] = true; - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitInclusionLHS3_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { - auto status = visitedInclusionLHS3_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_0(pLab); - } - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitInclusionLHS3_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS3_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_1(pLab); - } - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool RC11Driver::checkInclusion3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0.clear(); - visitedInclusionLHS3_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_1.clear(); - visitedInclusionLHS3_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_2.clear(); - visitedInclusionLHS3_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept3.clear(); - lhsAccept3.resize(g.getMaxStamp().get() + 1, false); - rhsAccept3.clear(); - rhsAccept3.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS3_2(lab); - for (auto i = 0u; i < lhsAccept3.size(); i++) { - if (lhsAccept3[i] && !rhsAccept3[i]) { - racyLab3 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RC11Driver::visitInclusionLHS4_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab4 = lab; - return false; - } - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS4_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS4_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS4_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_1(pLab, v)) - return false; - } - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::checkInclusion4(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS4_0.clear(); - visitedInclusionLHS4_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_1.clear(); - visitedInclusionLHS4_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_2.clear(); - visitedInclusionLHS4_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS4_2(lab, v); -} - -void RC11Driver::visitInclusionLHS5_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept5[lab->getStamp().get()] = true; - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitInclusionLHS5_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedInclusionLHS5_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_0(pLab); - } - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::left; -} - -void RC11Driver::visitInclusionLHS5_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && - llvm::dyn_cast(lab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(lab))) - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS5_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_1(pLab); - } - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool RC11Driver::checkInclusion5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0.clear(); - visitedInclusionLHS5_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_1.clear(); - visitedInclusionLHS5_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_2.clear(); - visitedInclusionLHS5_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept5.clear(); - lhsAccept5.resize(g.getMaxStamp().get() + 1, false); - rhsAccept5.clear(); - rhsAccept5.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS5_2(lab); - for (auto i = 0u; i < lhsAccept5.size(); i++) { - if (lhsAccept5[i] && !rhsAccept5[i]) { - racyLab5 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool RC11Driver::visitInclusionLHS6_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab6 = lab; - return false; - } - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS6_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::checkInclusion6(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS6_0.clear(); - visitedInclusionLHS6_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS6_1.clear(); - visitedInclusionLHS6_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS6_1(lab, v); -} - -bool RC11Driver::visitInclusionLHS7_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab7 = lab; - return false; - } - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::visitInclusionLHS7_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS7_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS7_0(pLab, v)) - return false; - } - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::checkInclusion7(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS7_0.clear(); - visitedInclusionLHS7_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS7_1.clear(); - visitedInclusionLHS7_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS7_1(lab, v); -} - -VerificationError RC11Driver::checkErrors(const EventLabel *lab, const EventLabel *&race) const -{ - if (!checkInclusion0(lab)) { - race = racyLab0; - return VerificationError::VE_AccessNonMalloc; - } - - if (!checkInclusion1(lab)) { - race = racyLab1; - return VerificationError::VE_DoubleFree; - } - - if (!checkInclusion2(lab)) { - race = racyLab2; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion3(lab)) { - race = racyLab3; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion4(lab)) { - race = racyLab4; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion5(lab)) { - race = racyLab5; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion6(lab)) { - race = racyLab6; - return VerificationError::VE_RaceNotAtomic; - } - - return VerificationError::VE_OK; -} - -std::vector -RC11Driver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const -{ - std::vector result; - - if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkInclusion7(lab)) { - racyLabs.push_back(racyLab7); - result.push_back(VerificationError::VE_WWRace); - } - - return result; -} - -bool RC11Driver::visitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_4[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_4(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_4(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_4[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_4[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_5[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_5[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_6(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_6[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_6[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_7(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_7[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease() && pLab->isSC() && - llvm::isa(pLab)) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_7[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_8(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_8[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_7[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_7(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastRelease()) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_9[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_9(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_8[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_9(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_9[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_9[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_10(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_10[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_10[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_11(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_11[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_11[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_12(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_12[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_12[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_13(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_13[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_13[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_14(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_14[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_14[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::visitAcyclic0_15(const EventLabel *lab) const -{ - auto &g = getGraph(); - - ++visitedAccepting0; - visitedAcyclic0_15[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_13[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_13(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_11[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_11(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_10[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_10(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_12[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_12(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_5[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_5(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_8[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_8(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_6[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_6(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isAtLeastAcquire()) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - { - auto &node = visitedAcyclic0_14[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_14(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - FOREACH_MAXIMAL(pLab, g, lab->view(1)) - if (true && pLab->isSC() && llvm::isa(pLab)) - { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = rf_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = co_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && - !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC()) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC()) { - auto &node = visitedAcyclic0_15[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_15(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - --visitedAccepting0; - visitedAcyclic0_15[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool RC11Driver::isAcyclic0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - if (!shouldVisitAcyclic0()) - return true; - - visitedAccepting0 = 0; - visitedAcyclic0_0.clear(); - visitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_1.clear(); - visitedAcyclic0_1.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_2.clear(); - visitedAcyclic0_2.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_3.clear(); - visitedAcyclic0_3.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_4.clear(); - visitedAcyclic0_4.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_5.clear(); - visitedAcyclic0_5.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_6.clear(); - visitedAcyclic0_6.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_7.clear(); - visitedAcyclic0_7.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_8.clear(); - visitedAcyclic0_8.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_9.clear(); - visitedAcyclic0_9.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_10.clear(); - visitedAcyclic0_10.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_11.clear(); - visitedAcyclic0_11.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_12.clear(); - visitedAcyclic0_12.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_13.clear(); - visitedAcyclic0_13.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_14.clear(); - visitedAcyclic0_14.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_15.clear(); - visitedAcyclic0_15.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic0_0(lab) && visitAcyclic0_1(lab) && visitAcyclic0_6(lab) && - visitAcyclic0_8(lab) && visitAcyclic0_10(lab) && visitAcyclic0_12(lab) && - visitAcyclic0_14(lab) && visitAcyclic0_15(lab); -} - -bool RC11Driver::shouldVisitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_0[lab->getStamp().get()] = NodeStatus::entered; - return false; - shouldVisitedAcyclic0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::shouldVisitAcyclic0_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isSC()) - if (auto pLab = lab; true) { - auto &status = shouldVisitedAcyclic0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !shouldVisitAcyclic0_0(pLab)) - return false; - } - shouldVisitedAcyclic0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool RC11Driver::shouldVisitAcyclic0(void) const -{ - auto &g = getGraph(); - - shouldVisitedAcyclic0_0.clear(); - shouldVisitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - shouldVisitedAcyclic0_1.clear(); - shouldVisitedAcyclic0_1.resize(g.getMaxStamp().get() + 1); - return false || std::any_of(label_begin(g), label_end(g), - [&](auto &lab) { return !shouldVisitAcyclic0_1(&lab); }); -} - -bool RC11Driver::isConsistent(const EventLabel *lab) const { return true && isAcyclic0(lab); } - -bool RC11Driver::isRecAcyclic(const EventLabel *lab) const -{ - visitedRecAccepting = 0; - return true; -} - -bool RC11Driver::isRecoveryValid(const EventLabel *lab) const { return isRecAcyclic(lab); } - -View RC11Driver::calcPPoRfBefore(const EventLabel *lab) const -{ - auto &g = getGraph(); - View pporf; - pporf.updateIdx(lab->getPos()); - - auto *pLab = g.getPreviousLabel(lab); - if (!pLab) - return pporf; - pporf.update(pLab->getPrefixView()); - if (auto *rLab = llvm::dyn_cast(pLab)) - pporf.update(rLab->getRf()->getPrefixView()); - if (auto *tsLab = llvm::dyn_cast(pLab)) - pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); - if (auto *tjLab = llvm::dyn_cast(pLab)) - pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); - return pporf; -} -std::unique_ptr RC11Driver::calculatePrefixView(const EventLabel *lab) const -{ - return std::make_unique(calcPPoRfBefore(lab)); -} - -const View &RC11Driver::getHbView(const EventLabel *lab) const { return lab->view(1); } - -bool RC11Driver::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(1); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector RC11Driver::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto &lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(&lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool RC11Driver::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(1).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(1).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator RC11Driver::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator RC11Driver::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(1).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(1).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator RC11Driver::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector RC11Driver::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInit()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector RC11Driver::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - std::vector rfAfter; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - return after; -} - -std::vector RC11Driver::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector RC11Driver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(1); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(1).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(1).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -RC11Driver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/RC11Driver.hpp b/src/RC11Driver.hpp deleted file mode 100644 index d971d8b..0000000 --- a/src/RC11Driver.hpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#ifndef __RC11_DRIVER_HPP__ -#define __RC11_DRIVER_HPP__ - -#include "ExecutionGraph.hpp" -#include "GenMCDriver.hpp" -#include "GraphIterators.hpp" -#include "MaximalIterator.hpp" -#include "VSet.hpp" -#include "VerificationError.hpp" -#include "config.h" -#include -#include - -class RC11Driver : public GenMCDriver { - -private: - enum class NodeStatus : unsigned char { unseen, entered, left }; - - struct NodeCountStatus { - NodeCountStatus() = default; - NodeCountStatus(uint16_t c, NodeStatus s) : count(c), status(s) {} - uint16_t count = 0; - NodeStatus status = NodeStatus::unseen; - }; - -public: - RC11Driver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); - - std::vector> calculateSaved(const EventLabel *lab); - std::vector calculateViews(const EventLabel *lab); - void updateMMViews(EventLabel *lab) override; - bool isDepTracking() const override; - bool isConsistent(const EventLabel *lab) const override; - VerificationError checkErrors(const EventLabel *lab, - const EventLabel *&race) const override; - std::vector - checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const; - bool isRecoveryValid(const EventLabel *lab) const override; - std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; - const View &getHbView(const EventLabel *lab) const override; - std::vector getCoherentStores(SAddr addr, Event read) override; - std::vector getCoherentRevisits(const WriteLabel *sLab, - const VectorClock &pporf) override; - llvm::iterator_range - getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; - -private: - bool isWriteRfBefore(Event a, Event b); - std::vector getInitRfsAtLoc(SAddr addr); - bool isHbOptRfBefore(const Event e, const Event write); - ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); - ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); - ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); - std::vector getMOOptRfAfter(const WriteLabel *sLab); - std::vector getMOInvOptRfAfter(const WriteLabel *sLab); - - void visitCalc0_0(const EventLabel *lab, View &calcRes); - void visitCalc0_1(const EventLabel *lab, View &calcRes); - void visitCalc0_2(const EventLabel *lab, View &calcRes); - - View calculate0(const EventLabel *lab); - - mutable std::vector visitedCalc0_0; - mutable std::vector visitedCalc0_1; - mutable std::vector visitedCalc0_2; - - void visitCalc1_0(const EventLabel *lab, View &calcRes); - void visitCalc1_1(const EventLabel *lab, View &calcRes); - void visitCalc1_2(const EventLabel *lab, View &calcRes); - void visitCalc1_3(const EventLabel *lab, View &calcRes); - void visitCalc1_4(const EventLabel *lab, View &calcRes); - void visitCalc1_5(const EventLabel *lab, View &calcRes); - void visitCalc1_6(const EventLabel *lab, View &calcRes); - - View calculate1(const EventLabel *lab); - - mutable std::vector visitedCalc1_0; - mutable std::vector visitedCalc1_1; - mutable std::vector visitedCalc1_2; - mutable std::vector visitedCalc1_3; - mutable std::vector visitedCalc1_4; - mutable std::vector visitedCalc1_5; - mutable std::vector visitedCalc1_6; - - bool visitInclusionLHS0_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS0_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion0(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS0_0; - mutable std::vector visitedInclusionLHS0_1; - mutable std::vector visitedInclusionRHS0_0; - mutable std::vector visitedInclusionRHS0_1; - - mutable std::vector lhsAccept0; - mutable std::vector rhsAccept0; - - mutable const EventLabel *racyLab0 = nullptr; - - void visitInclusionLHS1_0(const EventLabel *lab) const; - void visitInclusionLHS1_1(const EventLabel *lab) const; - - bool checkInclusion1(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS1_0; - mutable std::vector visitedInclusionLHS1_1; - - mutable std::vector lhsAccept1; - mutable std::vector rhsAccept1; - - mutable const EventLabel *racyLab1 = nullptr; - - bool visitInclusionLHS2_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion2(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS2_0; - mutable std::vector visitedInclusionLHS2_1; - mutable std::vector visitedInclusionLHS2_2; - mutable std::vector visitedInclusionRHS2_0; - mutable std::vector visitedInclusionRHS2_1; - - mutable std::vector lhsAccept2; - mutable std::vector rhsAccept2; - - mutable const EventLabel *racyLab2 = nullptr; - - void visitInclusionLHS3_0(const EventLabel *lab) const; - void visitInclusionLHS3_1(const EventLabel *lab) const; - void visitInclusionLHS3_2(const EventLabel *lab) const; - - bool checkInclusion3(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS3_0; - mutable std::vector visitedInclusionLHS3_1; - mutable std::vector visitedInclusionLHS3_2; - - mutable std::vector lhsAccept3; - mutable std::vector rhsAccept3; - - mutable const EventLabel *racyLab3 = nullptr; - - bool visitInclusionLHS4_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion4(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS4_0; - mutable std::vector visitedInclusionLHS4_1; - mutable std::vector visitedInclusionLHS4_2; - mutable std::vector visitedInclusionRHS4_0; - mutable std::vector visitedInclusionRHS4_1; - - mutable std::vector lhsAccept4; - mutable std::vector rhsAccept4; - - mutable const EventLabel *racyLab4 = nullptr; - - void visitInclusionLHS5_0(const EventLabel *lab) const; - void visitInclusionLHS5_1(const EventLabel *lab) const; - void visitInclusionLHS5_2(const EventLabel *lab) const; - - bool checkInclusion5(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS5_0; - mutable std::vector visitedInclusionLHS5_1; - mutable std::vector visitedInclusionLHS5_2; - - mutable std::vector lhsAccept5; - mutable std::vector rhsAccept5; - - mutable const EventLabel *racyLab5 = nullptr; - - bool visitInclusionLHS6_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS6_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion6(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS6_0; - mutable std::vector visitedInclusionLHS6_1; - mutable std::vector visitedInclusionRHS6_0; - mutable std::vector visitedInclusionRHS6_1; - - mutable std::vector lhsAccept6; - mutable std::vector rhsAccept6; - - mutable const EventLabel *racyLab6 = nullptr; - - bool visitInclusionLHS7_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS7_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion7(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS7_0; - mutable std::vector visitedInclusionLHS7_1; - mutable std::vector visitedInclusionRHS7_0; - mutable std::vector visitedInclusionRHS7_1; - - mutable std::vector lhsAccept7; - mutable std::vector rhsAccept7; - - mutable const EventLabel *racyLab7 = nullptr; - - bool visitAcyclic0_0(const EventLabel *lab) const; - bool visitAcyclic0_1(const EventLabel *lab) const; - bool visitAcyclic0_2(const EventLabel *lab) const; - bool visitAcyclic0_3(const EventLabel *lab) const; - bool visitAcyclic0_4(const EventLabel *lab) const; - bool visitAcyclic0_5(const EventLabel *lab) const; - bool visitAcyclic0_6(const EventLabel *lab) const; - bool visitAcyclic0_7(const EventLabel *lab) const; - bool visitAcyclic0_8(const EventLabel *lab) const; - bool visitAcyclic0_9(const EventLabel *lab) const; - bool visitAcyclic0_10(const EventLabel *lab) const; - bool visitAcyclic0_11(const EventLabel *lab) const; - bool visitAcyclic0_12(const EventLabel *lab) const; - bool visitAcyclic0_13(const EventLabel *lab) const; - bool visitAcyclic0_14(const EventLabel *lab) const; - bool visitAcyclic0_15(const EventLabel *lab) const; - - bool isAcyclic0(const EventLabel *lab) const; - - mutable std::vector visitedAcyclic0_0; - mutable std::vector visitedAcyclic0_1; - mutable std::vector visitedAcyclic0_2; - mutable std::vector visitedAcyclic0_3; - mutable std::vector visitedAcyclic0_4; - mutable std::vector visitedAcyclic0_5; - mutable std::vector visitedAcyclic0_6; - mutable std::vector visitedAcyclic0_7; - mutable std::vector visitedAcyclic0_8; - mutable std::vector visitedAcyclic0_9; - mutable std::vector visitedAcyclic0_10; - mutable std::vector visitedAcyclic0_11; - mutable std::vector visitedAcyclic0_12; - mutable std::vector visitedAcyclic0_13; - mutable std::vector visitedAcyclic0_14; - mutable std::vector visitedAcyclic0_15; - - mutable uint16_t visitedAccepting0 = 0; - bool shouldVisitAcyclic0_0(const EventLabel *lab) const; - bool shouldVisitAcyclic0_1(const EventLabel *lab) const; - - bool shouldVisitAcyclic0(void) const; - - mutable std::vector shouldVisitedAcyclic0_0; - mutable std::vector shouldVisitedAcyclic0_1; - - bool isRecAcyclic(const EventLabel *lab) const; - - mutable uint16_t visitedRecAccepting = 0; - void visitPPoRf0(const EventLabel *lab, View &pporf) const; - - View calcPPoRfBefore(const EventLabel *lab) const; - - mutable std::vector visitedPPoRf0; - - mutable std::vector> saved; - mutable std::vector views; -}; - -#endif /* __RC11_DRIVER_HPP__ */ diff --git a/src/DepTracker.hpp b/src/Runtime/DepTracker.hpp similarity index 93% rename from src/DepTracker.hpp rename to src/Runtime/DepTracker.hpp index 601428c..bd0008c 100644 --- a/src/DepTracker.hpp +++ b/src/Runtime/DepTracker.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DEP_TRACKER_HPP__ -#define __DEP_TRACKER_HPP__ +#ifndef GENMC_DEP_TRACKER_HPP +#define GENMC_DEP_TRACKER_HPP -#include "DepInfo.hpp" +#include "ExecutionGraph/DepInfo.hpp" #include #include @@ -67,6 +67,7 @@ class DepTracker { { ctrlDeps[tid].update(dataDeps[tid][src]); }; + void updateCtrlDeps(unsigned int tid, Event e) { ctrlDeps[tid].update(DepInfo(e)); }; /* Clears the dependencies calculated for thread TID */ void clearDeps(unsigned int tid) @@ -92,4 +93,4 @@ struct DepTrackerCloner { // DepTracker *operator()(DepTracker &&x) const { return new DepTracker(std::move(x)); } }; -#endif /* __DEP_TRACKER_HPP__ */ +#endif /* GENMC_DEP_TRACKER_HPP */ diff --git a/src/Execution.cpp b/src/Runtime/Execution.cpp similarity index 72% rename from src/Execution.cpp rename to src/Runtime/Execution.cpp index c080cae..553cc5f 100644 --- a/src/Execution.cpp +++ b/src/Runtime/Execution.cpp @@ -34,12 +34,12 @@ * Author: Michalis Kokologiannakis */ -#include "Error.hpp" -#include "Event.hpp" -#include "GenMCDriver.hpp" -#include "Interpreter.h" -#include "LLVMUtils.hpp" -#include "SExprVisitor.hpp" +#include "ExecutionGraph/Event.hpp" +#include "Runtime/Interpreter.h" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" +#include "Support/SExprVisitor.hpp" +#include "Verification/GenMCDriver.hpp" #include "llvm/ADT/APInt.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/IntrinsicLowering.h" @@ -91,9 +91,9 @@ using namespace llvm; ({ \ SVal __result; \ if (auto *iTyp = llvm::dyn_cast(typ)) \ - __result = (val).IntVal.getLimitedValue(); \ + __result = SVal((val).IntVal.getLimitedValue()); \ else \ - __result = (uintptr_t)(val).PointerVal; \ + __result = SVal((uintptr_t)(val).PointerVal); \ __result; \ }) @@ -203,16 +203,16 @@ EventLabel::EventLabelKind getReadKind(LoadInst &I) auto *md = I.getMetadata("genmc.attr"); if (!md) - return Kind::EL_Read; + return Kind::Read; auto *op = dyn_cast(md->getOperand(0)); BUG_ON(!op); auto flags = dyn_cast(op->getValue())->getZExtValue(); if (GENMC_KIND(flags) == GENMC_KIND_SPECUL) - return Kind::EL_SpeculativeRead; + return Kind::SpeculativeRead; else if (GENMC_KIND(flags) == GENMC_KIND_CONFIRM) - return Kind::EL_ConfirmingRead; + return Kind::ConfirmingRead; BUG(); } @@ -233,21 +233,21 @@ std::pair getCasKinds(At auto *md = I.getMetadata("genmc.attr"); if (!md) - return std::make_pair(Kind::EL_CasRead, Kind::EL_CasWrite); + return std::make_pair(Kind::CasRead, Kind::CasWrite); auto *op = dyn_cast(md->getOperand(0)); BUG_ON(!op); auto flags = dyn_cast(op->getValue())->getZExtValue(); if (!GENMC_KIND(flags)) - return std::make_pair(Kind::EL_CasRead, Kind::EL_CasWrite); + return std::make_pair(Kind::CasRead, Kind::CasWrite); if (GENMC_KIND(flags) == GENMC_KIND_HELPED) - return std::make_pair(Kind::EL_HelpedCasRead, Kind::EL_HelpedCasWrite); + return std::make_pair(Kind::HelpedCasRead, Kind::HelpedCasWrite); else if (GENMC_KIND(flags) == GENMC_KIND_HELPING) - return std::make_pair(Kind::EL_HelpingCas, Kind::EL_HelpingCas); + return std::make_pair(Kind::HelpingCas, Kind::HelpingCas); BUG_ON(GENMC_KIND(flags) != GENMC_KIND_CONFIRM); - return std::make_pair(Kind::EL_ConfirmingCasRead, Kind::EL_ConfirmingCasWrite); + return std::make_pair(Kind::ConfirmingCasRead, Kind::ConfirmingCasWrite); } std::pair getFaiKinds(AtomicRMWInst &I) @@ -256,14 +256,14 @@ std::pair getFaiKinds(At auto *md = I.getMetadata("genmc.attr"); if (!md) - return std::make_pair(Kind::EL_FaiRead, Kind::EL_FaiWrite); + return std::make_pair(Kind::FaiRead, Kind::FaiWrite); auto *op = dyn_cast(md->getOperand(0)); BUG_ON(!op); auto flags = dyn_cast(op->getValue())->getZExtValue(); if (GENMC_KIND(flags) == GENMC_KIND_NONVR) - return std::make_pair(Kind::EL_NoRetFaiRead, Kind::EL_NoRetFaiWrite); + return std::make_pair(Kind::NoRetFaiRead, Kind::NoRetFaiWrite); BUG(); } @@ -1610,7 +1610,7 @@ void Interpreter::visitLoadInst(LoadInst &I) /* ... and then the driver will provide the appropriate value */ #define IMPLEMENT_READ_VISIT(__kind) \ - case EventLabel::EventLabelKind::EL_##__kind: { \ + case EventLabel::EventLabelKind::__kind: { \ val = CALL_DRIVER_RESET_IF_NONE( \ handleLoad, __kind##Label::create(currPos(), I.getOrdering(), ptr, size, \ atyp, GET_DEPS(deps))); \ @@ -1703,8 +1703,7 @@ void Interpreter::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) getDataDeps(thr.id, I.getCompareOperand())); #define IMPLEMENT_CAS_VISIT(nameR, nameW) \ - case switchPair(EventLabel::EventLabelKind::EL_##nameR, \ - EventLabel::EventLabelKind::EL_##nameW): { \ + case switchPair(EventLabel::EventLabelKind::nameR, EventLabel::EventLabelKind::nameW): { \ ret = CALL_DRIVER_RESET_IF_NONE( \ handleLoad, \ nameR##Label::create(currPos(), I.getSuccessOrdering(), ptr, size, atyp, \ @@ -1735,7 +1734,7 @@ void Interpreter::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) IMPLEMENT_CAS_VISIT(CasRead, CasWrite); IMPLEMENT_CAS_VISIT(HelpedCasRead, HelpedCasWrite); IMPLEMENT_CAS_VISIT(ConfirmingCasRead, ConfirmingCasWrite); - case switchPair(EventLabel::EL_HelpingCas, EventLabel::EL_HelpingCas): + case switchPair(EventLabel::HelpingCas, EventLabel::HelpingCas): if (!CALL_DRIVER_RESET_IF_FALSE( handleHelpingCas, HelpingCasLabel::create(currPos(), I.getSuccessOrdering(), ptr, size, @@ -1821,8 +1820,7 @@ void Interpreter::visitAtomicRMWInst(AtomicRMWInst &I) getAddrPoDeps(thr.id), nullptr); #define IMPLEMENT_FAI_VISIT(nameR, nameW) \ - case switchPair(EventLabel::EventLabelKind::EL_##nameR, \ - EventLabel::EventLabelKind::EL_##nameW): { \ + case switchPair(EventLabel::EventLabelKind::nameR, EventLabel::EventLabelKind::nameW): { \ ret = CALL_DRIVER_RESET_IF_NONE( \ handleLoad, nameR##Label::create(currPos(), I.getOrdering(), ptr, size, \ atyp, I.getOperation(), val, \ @@ -2978,12 +2976,13 @@ void Interpreter::handleSystemError(SystemError code, const std::string &msg) { if (stopOnSystemErrors) { systemErrorNumber = code; - driver->reportError(currPos(), VerificationError::VE_SystemError, msg); + driver->reportError({currPos(), VerificationError::VE_SystemError, msg}); } else { WARN_ONCE(errorList.at(code), msg + "\n"); - CALL_DRIVER(handleStore, WriteLabel::create(currPos(), AtomicOrdering::Monotonic, - errnoAddr, getTypeSize(errnoTyp), - AType::Signed, static_cast(code))); + CALL_DRIVER(handleStore, + WriteLabel::create(currPos(), AtomicOrdering::Monotonic, errnoAddr, + getTypeSize(errnoTyp), AType::Signed, + SVal(static_cast(code)))); } } @@ -3003,7 +3002,7 @@ void Interpreter::handleLock(SAddr addr, ASize size, const EventDeps *deps) auto annot = ReadLabel::AnnotVP( NeExpr::create( RegisterExpr::create(size.getBits(), MI->idInfo.VID.at(I)), - ConcreteExpr::create(size.getBits(), 1)) + ConcreteExpr::create(size.getBits(), SVal(1))) .release()); auto ret = CALL_DRIVER_RESET_IF_NONE( handleLoad, @@ -3032,8 +3031,9 @@ void Interpreter::handleUnlock(SAddr addr, ASize size, const EventDeps *deps) // return; // } - CALL_DRIVER(handleStore, UnlockWriteLabel::create(currPos(), addr, size, GET_DEPS(deps))); - return; + CALL_DRIVER(handleStore, + UnlockWriteLabel::create(currPos(), AtomicOrdering::Release, addr, size, + AType::Signed, SVal(0), GET_DEPS(deps))); } void Interpreter::callAssertFail(Function *F, const std::vector &ArgVals, @@ -3046,13 +3046,14 @@ void Interpreter::callAssertFail(Function *F, const std::vector &A std::string((char *)getStaticAddr(GVTOP(ArgVals[0]))) : "Unknown"; - driver->reportError(currPos(), errT, err); + driver->reportError({currPos(), errT, err}); } void Interpreter::callOptBegin(Function *F, const std::vector &ArgVals, const std::unique_ptr &specialDeps) { auto expand = CALL_DRIVER(handleOptional, OptionalLabel::create(currPos())); + updateCtrlDeps(getCurThr().id, currPos()); // add a ctrl dep on optionals GenericValue result; result.IntVal = APInt(F->getReturnType()->getIntegerBitWidth(), expand, true); // signed @@ -3063,7 +3064,7 @@ void Interpreter::callOptBegin(Function *F, const std::vector &Arg void Interpreter::callLoopBegin(Function *F, const std::vector &ArgVals, const std::unique_ptr &specialDeps) { - CALL_DRIVER(handleLoopBegin, LoopBeginLabel::create(currPos())); + CALL_DRIVER(handleDummy, LoopBeginLabel::create(currPos())); } void Interpreter::callSpinStart(Function *F, const std::vector &ArgVals, @@ -3122,8 +3123,8 @@ void Interpreter::callMalloc(Function *F, const std::vector &ArgVa const std::unique_ptr &specialDeps) { if (!ArgVals[0].IntVal.isStrictlyPositive()) { - driver->reportError(currPos(), VerificationError::VE_Allocation, - "Invalid size in malloc()"); + driver->reportError( + {currPos(), VerificationError::VE_Allocation, "Invalid size in malloc()"}); return; } @@ -3147,13 +3148,13 @@ void Interpreter::callMallocAligned(Function *F, const std::vector auto size = ArgVals[1].IntVal.getLimitedValue(); if (!ArgVals[0].IntVal.isStrictlyPositive() || (align & (align - 1))) { - driver->reportError(currPos(), VerificationError::VE_Allocation, - "Invalid alignment in aligned_alloc()"); + driver->reportError({currPos(), VerificationError::VE_Allocation, + "Invalid alignment in aligned_alloc()"}); return; } if (!ArgVals[1].IntVal.isStrictlyPositive() || (size % align)) { - driver->reportError(currPos(), VerificationError::VE_Allocation, - "Invalid size in aligned_alloc()"); + driver->reportError({currPos(), VerificationError::VE_Allocation, + "Invalid size in aligned_alloc()"}); return; } @@ -3171,8 +3172,8 @@ void Interpreter::callPMalloc(Function *F, const std::vector &ArgV const std::unique_ptr &specialDeps) { if (!ArgVals[0].IntVal.isStrictlyPositive()) { - driver->reportError(currPos(), VerificationError::VE_Allocation, - "Invalid size in malloc()"); + driver->reportError( + {currPos(), VerificationError::VE_Allocation, "Invalid size in malloc()"}); return; } @@ -3221,8 +3222,8 @@ void Interpreter::callThreadCreate(Function *F, const std::vector GenericValue val, result; if (!calledFun) { - driver->reportError(currPos(), VerificationError::VE_InvalidCreate, - "Invalid argument in pthread_create(): NULL pointer"); + driver->reportError({currPos(), VerificationError::VE_InvalidCreate, + "Invalid argument in pthread_create(): NULL pointer"}); return; } @@ -3239,7 +3240,7 @@ void Interpreter::callThreadCreate(Function *F, const std::vector getAddrPoDeps(getCurThr().id), nullptr); int symm = ArgVals.size() > 3 ? ArgVals[3].IntVal.getLimitedValue() : -1; auto info = ThreadInfo(-1, currPos().thread, MI->idInfo.VID.at(calledFun), - (uintptr_t)ArgVals[2].PointerVal, symm); + SVal((uintptr_t)ArgVals[2].PointerVal), symm); auto tid = CALL_DRIVER(handleThreadCreate, ThreadCreateLabel::create(currPos(), info, GET_DEPS(deps))); @@ -3276,7 +3277,7 @@ void Interpreter::callThreadExit(Function *F, const std::vector &A freeAllocas(ECStack().back().Allocas); ECStack().pop_back(); } - popStackAndReturnValueToCaller(Type::getInt8PtrTy(F->getContext()), ArgVals[0]); + popStackAndReturnValueToCaller(F->getReturnType(), ArgVals[0]); } void Interpreter::callAtExit(Function *F, const std::vector &ArgVals, @@ -3354,7 +3355,7 @@ void Interpreter::callMutexTrylock(Function *F, const std::vector auto annot = ReadLabel::AnnotVP( NeExpr::create( RegisterExpr::create(ASize(size).getBits(), MI->idInfo.VID.at(I)), - ConcreteExpr::create(ASize(size).getBits(), 1)) + ConcreteExpr::create(ASize(size).getBits(), SVal(1))) .release()); auto ret = CALL_DRIVER(handleLoad, TrylockCasReadLabel::create(currPos(), ptr, size, std::move(annot), @@ -3444,8 +3445,8 @@ void Interpreter::callBarrierWait(Function *F, const std::vector & return; } -void Interpreter::callBarrierDestroy(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) +void Interpreter::callBarrierDes(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) { auto *barrier = (GenericValue *)GVTOP(ArgVals[0]); auto *typ = F->getReturnType(); @@ -3463,6 +3464,104 @@ void Interpreter::callBarrierDestroy(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{ + GenericValue *cvar = (GenericValue *)GVTOP(ArgVals[0]); + GenericValue *attr = (GenericValue *)GVTOP(ArgVals[1]); + auto *typ = F->getReturnType(); + auto size = getTypeSize(typ); + auto atyp = TYPE_TO_ATYPE(typ); + + if (attr) + WARN_ONCE("pthread-cvar-init-arg", + "Ignoring non-null argument given to pthread_cond_init.\n"); + + CALL_DRIVER(handleStore, WriteLabel::create(currPos(), AtomicOrdering::NotAtomic, cvar, + size, atyp, SVal(0), GET_DEPS(specialDeps))); + + GenericValue result; + result.IntVal = APInt(typ->getIntegerBitWidth(), 0); + returnValueToCaller(typ, result); +} + +void Interpreter::callCondVarWait(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{ + GenericValue *cvar = (GenericValue *)GVTOP(ArgVals[0]); + GenericValue *attr = (GenericValue *)GVTOP(ArgVals[1]); + auto *typ = F->getReturnType(); + auto size = getTypeSize(typ); + auto atyp = TYPE_TO_ATYPE(typ); + + auto *I = ECStack().back().CurInst->getPrevNode(); + auto annot = ReadLabel::AnnotVP( + SgtExpr::create( + RegisterExpr::create(ASize(size).getBits(), MI->idInfo.VID.at(I)), + ConcreteExpr::create(ASize(size).getBits(), SVal(0))) + .release()); + auto val = CALL_DRIVER(handleLoad, CondVarWaitReadLabel::create( + currPos(), AtomicOrdering::Monotonic, cvar, size, + atyp, GET_DEPS(specialDeps))) + .value(); + + returnValueToCaller(typ, SVAL_TO_GV(val, typ)); +} + +void Interpreter::callCondVarSignal(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{ + GenericValue *cvar = (GenericValue *)GVTOP(ArgVals[0]); + GenericValue *attr = (GenericValue *)GVTOP(ArgVals[1]); + auto *typ = F->getReturnType(); + auto size = getTypeSize(typ); + auto atyp = TYPE_TO_ATYPE(typ); + + CALL_DRIVER(handleStore, + CondVarSignalWriteLabel::create(currPos(), AtomicOrdering::Monotonic, cvar, + size, atyp, SVal(1), GET_DEPS(specialDeps))); + + GenericValue result; + result.IntVal = APInt(typ->getIntegerBitWidth(), 0); + returnValueToCaller(typ, result); +} + +void Interpreter::callCondVarBcast(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{ + GenericValue *cvar = (GenericValue *)GVTOP(ArgVals[0]); + GenericValue *attr = (GenericValue *)GVTOP(ArgVals[1]); + auto *typ = F->getReturnType(); + auto size = getTypeSize(typ); + auto atyp = TYPE_TO_ATYPE(typ); + + CALL_DRIVER(handleStore, + CondVarBcastWriteLabel::create(currPos(), AtomicOrdering::Monotonic, cvar, size, + atyp, SVal(1), GET_DEPS(specialDeps))); + + GenericValue result; + result.IntVal = APInt(typ->getIntegerBitWidth(), 0); + returnValueToCaller(typ, result); +} + +void Interpreter::callCondVarDestroy(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{ + GenericValue *cvar = (GenericValue *)GVTOP(ArgVals[0]); + GenericValue *attr = (GenericValue *)GVTOP(ArgVals[1]); + auto *typ = F->getReturnType(); + auto size = getTypeSize(typ); + auto atyp = TYPE_TO_ATYPE(typ); + + CALL_DRIVER(handleStore, + CondVarDestroyWriteLabel::create(currPos(), AtomicOrdering::Monotonic, cvar, + size, atyp, SVal(-1), GET_DEPS(specialDeps))); + + GenericValue result; + result.IntVal = APInt(typ->getIntegerBitWidth(), 0); + returnValueToCaller(typ, result); +} + void Interpreter::callHazptrAlloc(Function *F, const std::vector &ArgVals, const std::unique_ptr &specialDeps) { @@ -3475,7 +3574,6 @@ void Interpreter::callHazptrAlloc(Function *F, const std::vector & StorageType::ST_Volatile, AddressSpace::AS_Internal, GET_DEPS(deps))); returnValueToCaller(F->getReturnType(), SVAL_TO_GV(address, F->getReturnType())); - return; } void Interpreter::callHazptrProtect(Function *F, const std::vector &ArgVals, @@ -3484,8 +3582,7 @@ void Interpreter::callHazptrProtect(Function *F, const std::vector auto *hp = GVTOP(ArgVals[0]); auto *ptr = GVTOP(ArgVals[1]); - CALL_DRIVER(handleHpProtect, HpProtectLabel::create(currPos(), hp, ptr)); - return; + CALL_DRIVER(handleDummy, HpProtectLabel::create(currPos(), hp, ptr)); } void Interpreter::callHazptrClear(Function *F, const std::vector &ArgVals, @@ -3519,1540 +3616,193 @@ void Interpreter::callHazptrRetire(Function *F, const std::vector HpRetireLabel::create(currPos(), GVTOP(ArgVals[0]), GET_DEPS(deps))); } -static const std::unordered_map smpFenceTypes = { - {"mb", SmpFenceType::MB}, {"rmb", SmpFenceType::RMB}, {"wmb", SmpFenceType::WMB}, - {"ba", SmpFenceType::MBBA}, {"aa", SmpFenceType::MBAA}, {"as", SmpFenceType::MBAS}, - {"aul", SmpFenceType::MBAUL}, -}; - -void Interpreter::callSmpFenceLKMM(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - auto ft = smpFenceTypes.at((const char *)getStaticAddr(GVTOP(ArgVals[0]))); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), nullptr, nullptr); - CALL_DRIVER(handleFence, - SmpFenceLabelLKMM::create(currPos(), llvm::AtomicOrdering::Monotonic, ft, - GET_DEPS(deps))); - return; -} +/* These should be eliminated before they are called */ +void Interpreter::callAnnotateBegin(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{} -void Interpreter::callRCUReadLockLKMM(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - CALL_DRIVER(handleRCULockLKMM, RCULockLabelLKMM::create(currPos())); - return; -} +void Interpreter::callAnnotateEnd(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) +{} -void Interpreter::callRCUReadUnlockLKMM(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - CALL_DRIVER(handleRCUUnlockLKMM, RCUUnlockLabelLKMM::create(currPos())); - return; -} +bool isInternalCall(Function *F) { return internalFunNames.count(F->getName().str()); } -void Interpreter::callSynchronizeRCULKMM(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) +void Interpreter::callInternalFunction(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) { - CALL_DRIVER(handleRCUSyncLKMM, RCUSyncLabelLKMM::create(currPos())); - return; -} + auto fCode = internalFunNames.at(F->getName().str()); -void Interpreter::callCLFlush(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - CALL_DRIVER(handleCLFlush, - CLFlushLabel::create(currPos(), GVTOP(ArgVals[0]), GET_DEPS(deps))); + switch (fCode) { +#define HANDLE_FUNCTION(NUM, FUN, NAME) \ + case InternalFunctions::NAME: \ + call##NAME(F, ArgVals, specialDeps); \ + break; +#include "Runtime/InternalFunction.def" + default: + BUG(); + break; + } return; } -SVal Interpreter::getInodeTransStatus(void *inode, Type *intTyp) +std::vector +Interpreter::translateExternalCallArgs(Function *F, const std::vector &ArgVals) const { - auto inodeItrans = GET_INODE_ITRANSACTION_ADDR(inode); - return CALL_DRIVER(handleDskRead, - DskReadLabel::create(currPos(), inodeItrans, getTypeSize(intTyp), - TYPE_TO_ATYPE(intTyp))); -} + std::vector result; -void Interpreter::setInodeTransStatus(void *inode, Type *intTyp, SVal val) -{ - /* Transaction status modifications do not have any mapping (journal only) */ - auto inodeItrans = GET_INODE_ITRANSACTION_ADDR(inode); - CALL_DRIVER(handleDskWrite, - DskJnlWriteLabel::create(currPos(), inodeItrans, getTypeSize(intTyp), - TYPE_TO_ATYPE(intTyp), val, GET_JOURNAL_MAPPING(inode), - inode)); - return; + for (auto i = 0u; i < ArgVals.size(); ++i) { + /* Unfortunately, we cannot check for the F->arg_begin() type: + * the signature for printf might contain var_args (and thus it might be + * distance(arg_begin(), arg_end()) < ArgVals.size()), so we just + * check whether .PointerVal is non-null and hope for the best */ + if (GVTOP(ArgVals[i]) && SAddr(GVTOP(ArgVals[i])).isStatic()) { + auto transAddr = PTOGV(getStaticAddr(GVTOP(ArgVals[i]))); + result.push_back(transAddr); + } else { + result.push_back(ArgVals[i]); + } + } + return result; } -SVal Interpreter::readInodeSizeFS(void *inode, Type *intTyp, const std::unique_ptr &deps) +//===----------------------------------------------------------------------===// +// callFunction - Execute the specified function... +// +void Interpreter::callFunction(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps) { - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - - if (getProgramState() == ProgramState::Recovery) { - auto inodeIdisksize = GET_INODE_IDISKSIZE_ADDR(inode); - return CALL_DRIVER(handleDskRead, - DskReadLabel::create(currPos(), inodeIdisksize, asize, atyp)); + /* Special handling for internal calls */ + if (isInternalCall(F)) { + callInternalFunction(F, ArgVals, specialDeps); + return; } - auto inodeIsize = GET_INODE_ISIZE_ADDR(inode); - return CALL_DRIVER(handleLoad, ReadLabel::create(currPos(), AtomicOrdering::Acquire, - inodeIsize, asize, atyp, GET_DEPS(deps))) - .value(); -} - -void Interpreter::updateInodeSizeFS(void *inode, Type *intTyp, SVal newSize, - const std::unique_ptr &deps) -{ - auto inodeIsize = GET_INODE_ISIZE_ADDR(inode); - CALL_DRIVER(handleStore, WriteLabel::create(currPos(), AtomicOrdering::Release, inodeIsize, - getTypeSize(intTyp), TYPE_TO_ATYPE(intTyp), - newSize, GET_DEPS(deps))); - return; -} + assert(!specialDeps); + assert((ECStack().empty() || !&ECStack().back().Caller || + ECStack().back().Caller.arg_size() == ArgVals.size()) && + "Incorrect number of arguments passed into function call!"); + // Make a new stack frame... and fill it in. + ECStack().push_back(ExecutionContext()); -void Interpreter::updateInodeDisksizeFS(void *inode, Type *intTyp, SVal newSize, SVal ordDataBegin, - SVal ordDataEnd) -{ - auto inodeIdisksize = GET_INODE_IDISKSIZE_ADDR(inode); - auto ordDataRange = std::make_pair((void *)nullptr, (void *)nullptr); + ExecutionContext &StackFrame = ECStack().back(); + StackFrame.CurFunction = F; - /* In data=ordered mode, metadata are journaled after data are written */ - if (MI->fsInfo.journalData == JournalDataFS::ordered) { - auto *inodeData = (char *)GET_INODE_DATA_ADDR(inode); - ordDataRange.first = inodeData + ordDataBegin.get(); - ordDataRange.second = inodeData + ordDataEnd.get(); + // Special handling for external functions. + if (F->isDeclaration()) { + auto translated = translateExternalCallArgs(F, ArgVals); + auto Result = callExternalFunction(F, translated); + // Simulate a 'ret' instruction of the appropriate type. + popStackAndReturnValueToCaller(F->getReturnType(), Result); + return; } - /* Update disksize*/ - CALL_DRIVER(handleDskWrite, - DskMdWriteLabel::create(currPos(), inodeIdisksize, getTypeSize(intTyp), - TYPE_TO_ATYPE(intTyp), newSize, - GET_METADATA_MAPPING(inode), ordDataRange)); - - /* If there is no delayed allocation, we actually _wait_ for the write */ - if (MI->fsInfo.journalData == JournalDataFS::ordered && !MI->fsInfo.delalloc) - executeFsyncFS(inode, intTyp); - return; -} + // Get pointers to first LLVM BB & Instruction in function. + StackFrame.CurBB = &F->front(); + StackFrame.CurInst = StackFrame.CurBB->begin(); -void Interpreter::writeDataToDisk(void *buf, int bufOffset, void *inode, int inodeOffset, int count, - Type *dataTyp, const std::unique_ptr &deps) -{ - auto *inodeData = GET_INODE_DATA_ADDR(inode); - auto size = getTypeSize(dataTyp); - auto atyp = TYPE_TO_ATYPE(dataTyp); + // Run through the function arguments and initialize their values... + assert((ArgVals.size() == F->arg_size() || + (ArgVals.size() > F->arg_size() && F->getFunctionType()->isVarArg())) && + "Invalid number of values passed to function invocation!"); - for (auto i = 0u; i < count; i++) { - auto loadAddr = (char *)buf + bufOffset + i; - auto val = CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), AtomicOrdering::NotAtomic, - loadAddr, size, atyp, GET_DEPS(deps))) - .value(); + // Handle non-varargs arguments... + unsigned i = 0; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI, ++i) + SetValue(&*AI, ArgVals[i], StackFrame); - auto writeAddr = (char *)inodeData + inodeOffset + i; - CALL_DRIVER(handleDskWrite, DskWriteLabel::create(currPos(), writeAddr, size, atyp, - val, GET_DATA_MAPPING(inode))); - } - return; + // Handle varargs arguments... + StackFrame.VarArgs.assign(ArgVals.begin() + i, ArgVals.end()); } -void Interpreter::readDataFromDisk(void *inode, int inodeOffset, void *buf, int bufOffset, - int count, Type *dataTyp, const std::unique_ptr &deps) +std::string getFilenameFromMData(MDNode *node) { - auto *inodeData = GET_INODE_DATA_ADDR(inode); - auto asize = getTypeSize(dataTyp); - auto atyp = TYPE_TO_ATYPE(dataTyp); + const llvm::DILocation &loc = static_cast(*node); + llvm::StringRef file = loc.getFilename(); + llvm::StringRef dir = loc.getDirectory(); - for (auto i = 0u; i < count; i++) { - auto readAddr = (char *)inodeData + inodeOffset + i; - auto val = CALL_DRIVER(handleDskRead, - DskReadLabel::create(currPos(), readAddr, asize, atyp)); + BUG_ON(!file.size()); - auto storeAddr = (char *)buf + bufOffset + i; - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), AtomicOrdering::NotAtomic, storeAddr, - asize, atyp, val, GET_DEPS(deps))); + std::string absPath; + if (file.front() == '/') { + absPath = file.str(); + } else { + BUG_ON(!dir.size()); + absPath = dir.str(); + if (absPath.back() != '/') + absPath += "/"; + absPath += file; } - return; -} - -void Interpreter::updateDirNameInode(const std::string &name, Type *intTyp, SVal inode) -{ - auto *dirInode = getDirInode(); - auto inodeAddr = getInodeAddrFromName(name); - - executeFsyncFS(dirInode, intTyp); // \/ relies on inode layout - CALL_DRIVER(handleDskWrite, - DskDirWriteLabel::create(currPos(), inodeAddr, - getTypeSize(intTyp->getPointerTo()), AType::Pointer, - inode, GET_DATA_MAPPING(dirInode))); - if (MI->fsInfo.journalData == JournalDataFS::journal) - executeFsyncFS(dirInode, intTyp); - return; + return absPath; } -/* We may have to manipulate the flags at some point (depending on the model) */ -SVal Interpreter::checkOpenFlagsFS(SVal &flags, Type *intTyp) +void Interpreter::replayExecutionBefore(const VectorClock &before) { - if (flags.get() & ~GENMC_VALID_OPEN_FLAGS) { - handleSystemError(SystemError::SE_EINVAL, "Invalid flags used for open()"); - return SVal(-1); - } + reset(); + setExecState(ExecutionState::Replay); + setProgramState(ProgramState::Main); - if (flags.get() & GENMC_O_DSYNC) - WARN_ONCE("open-dsync-osync", "O_DSYNC encountered. Assuming O_SYNC...\n"); + /* We have to replay all threads in order to get debug metadata */ + for (auto i = 0u; i < before.size(); i++) { + auto &thr = getThrById(i); + if (thr.isMain()) + thr.ECStack = mainECStack; + else + thr.ECStack = thr.initEC; + thr.prefixLOC.clear(); + thr.prefixLOC.resize(before.getMax(i) + 2); /* Grow since it can be accessed */ + scheduleThread(i); + if (thr.threadFun == recoveryRoutine) + setProgramState(ProgramState::Recovery); + /* Make sure to refetch references within the loop (invalidation danger) */ + while ((int)getCurThr().globalInstructions < before.getMax(i)) { + int snap = getCurThr().globalInstructions; + ExecutionContext &SF = ECStack().back(); + Instruction &I = *SF.CurInst++; + visit(I); - return SVal(0); -} + /* Collect metadata only for global instructions */ + if (getCurThr().globalInstructions == snap) + continue; + /* If there are no metadata for this instruction, skip */ + if (!I.getMetadata("dbg")) + continue; -SVal Interpreter::executeInodeLookupFS(const std::string &filename, Type *intTyp) -{ - auto inTrans = getInodeTransStatus(getDirInode(), intTyp); - if (inTrans == SVal(1)) { - getCurThr().rollToSnapshot(); - getCurThr().block(BlockageType::Cons); - return SVal(42); /* propagate block */ - } + /* Store relevant trace information in the appropriate spot */ + int line = I.getDebugLoc().getLine(); + std::string file = getFilenameFromMData(I.getMetadata("dbg")); + getCurThr().prefixLOC[snap + 1] = std::make_pair(line, file); - /* Fetch the address where the inode should be and read the contents */ - auto inodeAddr = getInodeAddrFromName(filename); - return CALL_DRIVER(handleDskRead, DskReadLabel::create(currPos(), inodeAddr, - getTypeSize(intTyp->getPointerTo()), - AType::Pointer)); -} - -SVal Interpreter::executeInodeCreateFS(const std::string &filename, Type *intTyp, - const std::unique_ptr &deps) -{ - /* Allocate enough space for the inode... */ - unsigned int inodeSize = getTypeSize(MI->fsInfo.inodeTyp); - auto *info = getVarNameInfo(nullptr, StorageDuration::SD_Heap, AddressSpace::AS_Internal, - "inode"); - auto *inode = - (void *)CALL_DRIVER( - handleMalloc, - MallocLabel::create(currPos(), inodeSize, alignof(std::max_align_t), - StorageDuration::SD_Heap, StorageType::ST_Durable, - AddressSpace::AS_Internal, info, - std::string("__inode_") + filename, GET_DEPS(deps))) - .get(); - - /* ... properly initialize its fields... */ - auto inodeLock = GET_INODE_LOCK_ADDR(inode); - auto inodeIsize = GET_INODE_ISIZE_ADDR(inode); - - auto zero = SVal(0); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - CALL_DRIVER(handleStore, WriteLabel::create(currPos(), AtomicOrdering::Release, inodeLock, - asize, atyp, zero, GET_DEPS(deps))); - CALL_DRIVER(handleStore, WriteLabel::create(currPos(), AtomicOrdering::Release, inodeIsize, - asize, atyp, zero, GET_DEPS(deps))); - setInodeTransStatus(inode, intTyp, zero); - updateInodeDisksizeFS(inode, intTyp, zero, zero, zero); - - /* ... set the newly allocated inode to the appropriate address */ - updateDirNameInode(filename, intTyp, SVal((uintptr_t)inode)); - - return SVal((uintptr_t)inode); -} - -/* On success, returns a non-null pointer value that corresponds - * to the address of FILE's inode. Success: either if the inode was - * already created, or flags contain O_CREAT and the inode was - * created. */ -SVal Interpreter::executeLookupOpenFS(const std::string &file, SVal &flags, Type *intTyp, - const std::unique_ptr &deps) -{ - /* If O_CREAT was not specified, just do the lookup */ - if (!(flags.get() & GENMC_O_CREAT)) - return executeInodeLookupFS(file, intTyp); - - /* Otherwise, we need to take the dir inode's lock */ - auto dirLock = GET_INODE_LOCK_ADDR(getDirInode()); - handleLock(dirLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return SVal(42); + /* If the instruction maps to more than one events, we have to fill more + * spots */ + for (auto i = snap + 2; + i <= std::min((int)getCurThr().globalInstructions, before.getMax(i)); + i++) + getCurThr().prefixLOC[i] = std::make_pair(line, file); + } } - - /* Check if the corresponding inode already exists */ - auto inode = executeInodeLookupFS(file, intTyp); - if (getCurThr().isBlocked()) - return inode; /* propagate the block */ - - /* Return the inode, if it already exists */ - if ((void *)inode.get() != nullptr) - goto unlock; - - /* Otherwise, we create an inode */ - inode = executeInodeCreateFS(file, intTyp, deps); - - /* If we created the inode, we will not truncate it - * (This should not happen here, but since we only model ext4 it doesn't matter) */ - flags &= SVal(~GENMC_O_TRUNC); /* Compatible with LLVM <= 4 */ - -unlock: - handleUnlock(dirLock, getTypeSize(intTyp), &*deps); - return inode; -} - -SVal Interpreter::executeOpenFS(const std::string &filename, SVal flags, SVal inode, Type *intTyp, - const std::unique_ptr &deps) -{ - Type *intPtrType = intTyp->getPointerTo(); - - /* Get a fresh fd */ - auto fd = CALL_DRIVER(handleDskOpen, - DskOpenLabel::create(currPos(), filename, getTypeSize(intTyp))); - - /* Also a name for the description */ - std::string varname("__file_"); - raw_string_ostream sname(varname); - sname << filename << "_" << getCurThr().id << "_" << getCurThr().globalInstructions; - - /* We allocate space for the file description... */ - auto fileSize = getTypeSize(MI->fsInfo.fileTyp); - auto *info = getVarNameInfo(nullptr, StorageDuration::SD_Heap, AddressSpace::AS_Internal, - "file"); - auto *file = (void *)CALL_DRIVER( - handleMalloc, - MallocLabel::create(currPos(), fileSize, alignof(std::max_align_t), - StorageDuration::SD_Heap, StorageType::ST_Volatile, - AddressSpace::AS_Internal, info, sname.str(), - GET_DEPS(deps))) - .get(); - - /* ... and initialize its fields */ - auto fileInode = GET_FILE_INODE_ADDR(file); - auto fileCount = GET_FILE_COUNT_ADDR(file); - auto fileFlags = GET_FILE_FLAGS_ADDR(file); - auto filePosLock = GET_FILE_POS_LOCK_ADDR(file); - auto fileOffset = GET_FILE_OFFSET_ADDR(file); - auto atyp = TYPE_TO_ATYPE(intTyp); - - CALL_DRIVER(handleStore, WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileInode, getTypeSize(intPtrType), - AType::Pointer, inode, GET_DEPS(deps))); - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, fileFlags, - getTypeSize(intTyp), atyp, flags, GET_DEPS(deps))); - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, fileOffset, - getTypeSize(intTyp), atyp, SVal(0), GET_DEPS(deps))); - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::Release, filePosLock, - getTypeSize(intTyp), atyp, SVal(0), GET_DEPS(deps))); - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::Release, fileCount, - getTypeSize(intTyp), atyp, SVal(1), GET_DEPS(deps))); - setFdToFile(fd.get(), file); - return fd; } -SVal Interpreter::executeTruncateFS(SVal inode, SVal length, Type *intTyp, - const std::unique_ptr &deps) +void Interpreter::runAtExitHandlers() { - /* length is a signed integer -- careful because it's long */ - if (length.getSigned() < 0) { - handleSystemError(SystemError::SE_EINVAL, "Invalid length for truncate()"); - return SVal(-1); - } - - /* Get inode's lock (as in do_truncate()) */ - auto inodeLock = GET_INODE_LOCK_ADDR((void *)inode.get()); - handleLock(inodeLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return SVal(42); - } - - SVal ret = SVal(0); - SVal ordRangeBegin = SVal(0), ordRangeEnd = SVal(0); + auto oldState = getProgramState(); + setProgramState(ProgramState::Dtors); + while (!dynState.AtExitHandlers.empty()) { + scheduleThread(0); + callFunction(dynState.AtExitHandlers.back(), std::vector(), nullptr); + dynState.AtExitHandlers.pop_back(); - /* Check if we are actually extending the file */ - auto oldIsize = readInodeSizeFS((void *)inode.get(), intTyp, deps); - if (length.getSigned() > oldIsize.getSigned()) { - if (length.getSigned() >= MI->fsInfo.maxFileSize) { - handleSystemError(SystemError::SE_EFBIG, "Length too big in truncate()"); - ret = SVal(-1); - goto out; - } - zeroDskRangeFS((void *)inode.get(), oldIsize, length, - Type::getInt8Ty(intTyp->getContext())); - ordRangeBegin = oldIsize; - ordRangeEnd = length; - } - - /* Update inode's size (ext4_setattr()) */ - updateInodeDisksizeFS((void *)inode.get(), intTyp, length, ordRangeBegin, ordRangeEnd); - updateInodeSizeFS((void *)inode.get(), intTyp, length, deps); - - if (MI->fsInfo.journalData >= JournalDataFS::ordered) - executeFsyncFS((void *)inode.get(), intTyp); - -out: - /* Release inode's lock */ - handleUnlock(inodeLock, getTypeSize(intTyp), &*deps); - return ret; -} - -void Interpreter::callOpenFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - std::string filename = (const char *)getStaticAddr(GVTOP(ArgVals[0])); - SVal flags = ArgVals[1].IntVal.getLimitedValue(); - Type *intTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* Check the flags passed -- we ignore mode_t for the time being */ - auto retO = checkOpenFlagsFS(flags, intTyp); - if (retO == SVal(-1)) { - returnValueToCaller(F->getReturnType(), SVAL_TO_GV(retO, F->getReturnType())); - return; - } - - /* Try and find the requested inode */ - auto inode = executeLookupOpenFS(filename, flags, intTyp, deps); - if (getCurThr().isBlocked()) - return; - - /* Inode not found -- cannot open file */ - if ((void *)inode.get() == nullptr) { - handleSystemError(SystemError::SE_ENOENT, "File does not exist in open()"); - returnValueToCaller(F->getReturnType(), INT_TO_GV(intTyp, -1)); - return; - } - - /* We allocate a new file description pointing to the file's inode... */ - auto fd = executeOpenFS(filename, flags, inode, intTyp, deps); - - /* ... and truncate if necessary */ - if (flags.get() & GENMC_O_TRUNC) { - if (!(GENMC_OPEN_FMODE(flags.get()) & GENMC_FMODE_WRITE)) { - driver->reportError(currPos(), VerificationError::VE_InvalidTruncate, - "File is not open for writing"); - returnValueToCaller(F->getReturnType(), INT_TO_GV(F->getReturnType(), -1)); - return; - } - auto ret = executeTruncateFS(inode, SVal(0), intTyp, deps); - if (ret == SVal(42)) - return; /* Failed to acquire inode's lock... */ - if (ret == SVal(-1)) { - returnValueToCaller(F->getReturnType(), INT_TO_GV(F->getReturnType(), -1)); - return; /* Something went really wrong (negative length?) */ - } - } - - returnValueToCaller(F->getReturnType(), SVAL_TO_GV(fd, F->getReturnType())); - return; -} - -void Interpreter::callCreatFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - Type *intTyp = F->getReturnType(); - auto flags = INT_TO_GV(intTyp, GENMC_O_CREAT | GENMC_O_WRONLY | GENMC_O_TRUNC); - callOpenFS(F, {ArgVals[0], flags, ArgVals[1]}, specialDeps); - return; -} - -void Interpreter::executeReleaseFileFS(void *fileDesc, Type *intTyp, - const std::unique_ptr &deps) -{ - /* Nothing for auto_da_alloc_close */ - - /* Free file description */ - CALL_DRIVER(handleFree, FreeLabel::create(currPos(), fileDesc, GET_DEPS(deps))); - return; -} - -SVal Interpreter::executeCloseFS(SVal fd, Type *intTyp, const std::unique_ptr &deps) -{ - /* If it's not a valid open fd, report the error */ - auto *fileDesc = getFileFromFd(fd.get()); - if (!fileDesc) { - handleSystemError(SystemError::SE_EBADF, "Invalid fd used in close()"); - return SVal(-1); - } - - /* Decrease the count for this file */ - auto fileCount = GET_FILE_COUNT_ADDR(fileDesc); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - auto ret = CALL_DRIVER(handleLoad, - FaiReadLabel::create(currPos(), AtomicOrdering::AcquireRelease, - fileCount, asize, atyp, AtomicRMWInst::Sub, - SVal(1), GET_DEPS(deps))) - .value(); - - auto newVal = executeAtomicRMWOperation(ret, SVal(1), asize, AtomicRMWInst::Sub); - - CALL_DRIVER(handleStore, - FaiWriteLabel::create(currPos(), AtomicOrdering::AcquireRelease, fileCount, - asize, atyp, newVal, GET_DEPS(deps))); - - /* Check if it is the last reference to a file description */ - if (newVal == SVal(0)) - executeReleaseFileFS(fileDesc, intTyp, deps); - - return SVal(0); -} - -void Interpreter::callCloseFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - SVal fd = ArgVals[0].IntVal.getLimitedValue(); - Type *intTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* Close the file and return result to user */ - auto result = executeCloseFS(fd, intTyp, deps); - returnValueToCaller(intTyp, SVAL_TO_GV(result, intTyp)); - return; -} - -SVal Interpreter::executeLinkFS(const std::string &newpath, SVal oldInode, Type *intTyp) -{ - updateDirNameInode(newpath, intTyp, oldInode); - return SVal(0); -} - -void Interpreter::callLinkFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - std::string oldpath = (const char *)getStaticAddr(GVTOP(ArgVals[0])); - std::string newpath = (const char *)getStaticAddr(GVTOP(ArgVals[1])); - Type *intTyp = F->getReturnType(); - GenericValue result; - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - auto dirLock = GET_INODE_LOCK_ADDR(getDirInode()); - SVal source, target; - - /* Since we have a single-directory structure, link boils down to a simple cs */ - handleLock(dirLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - source = executeInodeLookupFS(oldpath, intTyp); - if (getCurThr().isBlocked()) - return; - - /* If no such entry found, exit */ - if ((void *)source.get() == nullptr) { - handleSystemError(SystemError::SE_ENOENT, "No entry found for oldpath at link()"); - result = INT_TO_GV(intTyp, -1); - goto exit; - } - - /* Otherwise, check if newpath exists */ - target = executeInodeLookupFS(newpath, intTyp); - if (target.get()) { - handleSystemError(SystemError::SE_EEXIST, "The entry for newpath exists at link()"); - result = INT_TO_GV(intTyp, -1); - goto exit; - } - - result = SVAL_TO_GV(executeLinkFS(newpath, source, intTyp), F->getReturnType()); - -exit: - handleUnlock(dirLock, getTypeSize(intTyp), &*deps); - returnValueToCaller(F->getReturnType(), result); - return; -} - -SVal Interpreter::executeUnlinkFS(const std::string &pathname, Type *intTyp) -{ - /* Unlink inode */ - updateDirNameInode(pathname, intTyp, SVal(0)); - return SVal(0); -} - -void Interpreter::callUnlinkFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - std::string pathname = (const char *)getStaticAddr(GVTOP(ArgVals[0])); - Type *intTyp = F->getReturnType(); - GenericValue result; - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - auto dirLock = GET_INODE_LOCK_ADDR(getDirInode()); - handleLock(dirLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - auto inode = executeInodeLookupFS(pathname, intTyp); - if (getCurThr().isBlocked()) - return; - - /* Check if component exists */ - if ((void *)inode.get() == nullptr) { - handleSystemError(SystemError::SE_ENOENT, "Component does not exist for unlink()"); - result = INT_TO_GV(intTyp, -1); - goto exit; - } - - result = SVAL_TO_GV(executeUnlinkFS(pathname, intTyp), F->getReturnType()); - -exit: - handleUnlock(dirLock, getTypeSize(intTyp), &*deps); - - returnValueToCaller(F->getReturnType(), result); - return; -} - -SVal Interpreter::executeRenameFS(const std::string &oldpath, SVal oldInode, - const std::string &newpath, SVal newInode, Type *intTyp) -{ - Type *intPtrTyp = intTyp->getPointerTo(); - - /* If hard links referring on the same file */ - if (oldInode == newInode) - return SVal(0); - - /* - * Do the actual rename operation within a transaction - * We don't have to do actual locking, since i_transaction - * is protected by the inode's lock - */ - setInodeTransStatus(getDirInode(), intTyp, SVal(1)); - - /* Make new name point to old name's inode and delete old name */ - auto result = executeLinkFS(newpath, oldInode, intTyp); - BUG_ON(result.getSigned() == -1); - result = executeUnlinkFS(oldpath, intTyp); - - setInodeTransStatus(getDirInode(), intTyp, SVal(0)); - - return result; -} - -void Interpreter::callRenameFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - std::string oldpath = (const char *)getStaticAddr(GVTOP(ArgVals[0])); - std::string newpath = (const char *)getStaticAddr(GVTOP(ArgVals[1])); - Type *intTyp = F->getReturnType(); - GenericValue result; - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - auto dirLock = GET_INODE_LOCK_ADDR(getDirInode()); - handleLock(dirLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - /* Try to find source inode */ - SVal source, target; - source = executeInodeLookupFS(oldpath, intTyp); - if (getCurThr().isBlocked()) - return; - if ((void *)source.get() == nullptr) { - handleSystemError(SystemError::SE_ENOENT, "Oldpath does not exist for rename()"); - result = INT_TO_GV(intTyp, -1); - goto exit; /* Use gotos since we might add support for more flags/error checks */ - } - - /* Try to find target inode */ - target = executeInodeLookupFS(newpath, intTyp); - if (getCurThr().isBlocked()) - return; - - result = SVAL_TO_GV(executeRenameFS(oldpath, source, newpath, target, intTyp), - F->getReturnType()); - -exit: - handleUnlock(dirLock, getTypeSize(intTyp), &*deps); - - returnValueToCaller(F->getReturnType(), result); - return; -} - -void Interpreter::callTruncateFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - std::string filename = (const char *)getStaticAddr(GVTOP(ArgVals[0])); - auto length = ArgVals[1].IntVal.getLimitedValue(); - Type *intTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - auto dirLock = GET_INODE_LOCK_ADDR(getDirInode()); - handleLock(dirLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - /* Try and find the requested inode */ - auto inode = executeInodeLookupFS(filename, intTyp); - if (getCurThr().isBlocked()) - return; - - handleUnlock(dirLock, getTypeSize(intTyp), &*deps); - - /* Inode not found -- cannot truncate file */ - if ((void *)inode.get() == nullptr) { - handleSystemError(SystemError::SE_ENOENT, "File does not exist in truncate()"); - returnValueToCaller(F->getReturnType(), INT_TO_GV(intTyp, -1)); - return; - } - - auto ret = executeTruncateFS(inode, length, intTyp, deps); - if (ret == SVal(42)) - return; /* Failed to acquire inode's lock... */ - - returnValueToCaller(F->getReturnType(), SVAL_TO_GV(ret, F->getReturnType())); - return; -} - -bool Interpreter::shouldUpdateInodeDisksizeFS(void *inode, Type *intTyp, SVal iSize, SVal wOffset, - SVal countVal, SVal &dSize) -{ - /* ugly hack for comparing different length APInts... */ - auto size = iSize.get(); - auto offset = wOffset.get(); - auto count = countVal.get(); - - /* We should update if we are appending in the same (pre-allocated) block */ - auto bi = size % MI->fsInfo.blockSize; - auto rb = MI->fsInfo.blockSize - bi; - auto be = size + rb; - bool shouldUpdate = ((offset <= size && size < offset + count) || - (offset < be && be <= offset + count) || - (size <= offset && offset + count <= be)) && - bi > 0; - if (!shouldUpdate) - return false; - - /* Calculate the new disksize */ - dSize = SVal(std::min(be, offset + count)); - return true; -} - -SVal Interpreter::executeReadFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, - SVal count, const std::unique_ptr &deps) -{ - Type *intPtrType = intTyp->getPointerTo(); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - SVal nr = SVal(-1); - - /* Check if we can read from the file */ - auto flagsOffset = GET_FILE_FLAGS_ADDR(file); - auto flags = - CALL_DRIVER(handleLoad, ReadLabel::create(currPos(), AtomicOrdering::NotAtomic, - flagsOffset, asize, atyp, GET_DEPS(deps))) - .value(); - if (!(GENMC_OPEN_FMODE(flags.get()) & GENMC_FMODE_READ)) { - handleSystemError(SystemError::SE_EBADF, "File not opened for reading in read()"); - return nr; - } - - /* Fetch the address of the inode */ - auto fileInode = GET_FILE_INODE_ADDR(file); - auto *inode = - (void *)CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::Monotonic, - fileInode, getTypeSize(intPtrType), - AType::Pointer, GET_DEPS(deps))) - .value() - .get(); - - /* Read the inode size and check whether we are reading past EOF */ - auto iSize = readInodeSizeFS(inode, intTyp, deps); - if (offset.sge(iSize)) { - nr = SVal(0); - return nr; - } - - /* Calculate how many bytes we can actually read from the file... */ - nr = iSize - offset; - nr = (nr.getSigned() >= count.getSigned()) ? count : nr; - - /* ... and go ahead and read them one by one. (Here we cheat and not make - * the read buffered, since it doesn't make a difference.) */ - readDataFromDisk(inode, offset.getSigned(), buf, 0, nr.getSigned(), bufElemTyp, deps); - - if (MI->fsInfo.journalData == JournalDataFS::journal) { - auto inTrans = getInodeTransStatus(inode, intTyp); - if (inTrans == SVal(1)) { - getCurThr().rollToSnapshot(); - getCurThr().block(BlockageType::Cons); - return SVal(42); /* propagate block */ - } - } - return nr; -} - -void Interpreter::callReadFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - GenericValue *buf = (GenericValue *)GVTOP(ArgVals[1]); - SVal count = ArgVals[2].IntVal.getLimitedValue(); - Type *bufElemTyp = Type::getInt8Ty(F->getContext()); - Type *intTyp = F->getFunctionType()->getParamType(0); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* We get the address of the file description, from which we will get - * the reading offset, as well as the address of the inode. */ - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in read()"); - returnValueToCaller(retTyp, INT_TO_GV(intTyp, -1)); - return; - } - - /* First, we must get the file's lock. If we fail to acquire the lock, - * we reset the EE to this instruction */ - auto fileLock = GET_FILE_POS_LOCK_ADDR(file); - handleLock(fileLock, asize, &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - /* Now we can read the offset at which we will try to read... */ - auto fileOffset = GET_FILE_OFFSET_ADDR(file); - auto offset = CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, GET_DEPS(deps))) - .value(); - - auto nr = executeReadFS(file, intTyp, buf, bufElemTyp, offset, count, deps); - if (getCurThr().isBlocked()) - return; - - /* If the read succeeded, update the offset in the file description... */ - if (nr.getSigned() >= 0) { - offset += nr; - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, offset, GET_DEPS(deps))); - } - - /* ...and then release the description's lock */ - handleUnlock(fileLock, asize, &*deps); - - /* Return #bytes read -- if successful, fullfills the read request in full */ - returnValueToCaller(retTyp, SVAL_TO_GV(nr, retTyp)); - return; -} - -void Interpreter::zeroDskRangeFS(void *inode, SVal start, SVal end, Type *writeIntTyp) -{ - auto *dataOffset = (char *)GET_INODE_DATA_ADDR(inode); - auto asize = getTypeSize(writeIntTyp); - auto atyp = TYPE_TO_ATYPE(writeIntTyp); - for (auto i = start.get(); i < end.get(); i++) { - auto addr = dataOffset + i; - CALL_DRIVER(handleDskWrite, - DskWriteLabel::create(currPos(), addr, asize, atyp, SVal(0), - GET_DATA_MAPPING(inode))); - } - return; -} - -SVal Interpreter::executeWriteChecksFS(void *inode, Type *intTyp, SVal flags, SVal offset, - SVal count, SVal &wOffset, - const std::unique_ptr &deps) -{ - if (count.getSigned() <= 0) - return count; - - /* Non-POSIX-compliant behavior for pwrite() -- see ext4_write_checks() */ - wOffset = offset; - if (flags.get() & GENMC_O_APPEND) - wOffset = readInodeSizeFS(inode, intTyp, deps); - - /* Check if the maximum file size is going to be exceeded */ - if (wOffset.getSigned() >= MI->fsInfo.maxFileSize) { - handleSystemError(SystemError::SE_EFBIG, "Offset too big in write()"); - return SVal(-1); - } - return SVal( - std::min(count.getSigned(), (int64_t)MI->fsInfo.maxFileSize - wOffset.getSigned())); -} - -SVal Interpreter::executeBufferedWriteFS(void *inode, Type *intTyp, void *buf, Type *bufElemTyp, - SVal wOffset, SVal count, - const std::unique_ptr &deps) -{ - auto *inodeData = GET_INODE_DATA_ADDR(inode); - - /* Special care for appends and past-EOF writes (we zero ranges lazily) */ - SVal dSize, ordRangeBegin; - auto iSize = readInodeSizeFS(inode, intTyp, deps); - if (MI->fsInfo.delalloc && - shouldUpdateInodeDisksizeFS(inode, intTyp, iSize, wOffset, count, dSize)) { - zeroDskRangeFS(inode, iSize, dSize, bufElemTyp); - updateInodeDisksizeFS(inode, intTyp, dSize, iSize, dSize); - } - if (wOffset.getSigned() > iSize.getSigned()) - zeroDskRangeFS(inode, iSize, wOffset, bufElemTyp); - - /* Block-wise write (we know that count > 0 at this point) */ - ordRangeBegin = 0; - auto dataCount = count.get(); - auto bufOffset = 0; - auto inodeOffset = wOffset.get(); - do { - /* Calculate amount to write and align write */ - auto bytes = std::min(MI->fsInfo.blockSize, - dataCount); /* should be small enough */ - auto blockIndex = inodeOffset % MI->fsInfo.blockSize; - auto blockRem = MI->fsInfo.blockSize - blockIndex; - if (blockIndex != 0 && bytes > blockRem) - bytes = blockRem; - - if (MI->fsInfo.journalData == JournalDataFS::journal) - setInodeTransStatus(inode, intTyp, SVal(1)); - - /* Write data */ - writeDataToDisk(buf, bufOffset, inode, inodeOffset, bytes, bufElemTyp, deps); - - /* Update the inode's size, if necessary */ - SVal newSize = SVal(inodeOffset + bytes); - if (newSize.getSigned() > readInodeSizeFS(inode, intTyp, deps).getSigned()) { - updateInodeDisksizeFS(inode, intTyp, newSize, ordRangeBegin, newSize); - updateInodeSizeFS(inode, intTyp, newSize, deps); - ordRangeBegin = newSize; - } - - if (MI->fsInfo.journalData == JournalDataFS::journal) { - setInodeTransStatus(inode, intTyp, SVal(0)); - executeFsyncFS(inode, intTyp); - } - - bufOffset += bytes; - inodeOffset += bytes; - dataCount -= bytes; - } while (dataCount); - - return count; -} - -SVal Interpreter::executeWriteFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, - SVal count, const std::unique_ptr &deps) -{ - Type *intPtrType = intTyp->getPointerTo(); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - - /* Check if we can write to the file */ - auto flagsOffset = GET_FILE_FLAGS_ADDR(file); - auto flags = - CALL_DRIVER(handleLoad, ReadLabel::create(currPos(), AtomicOrdering::NotAtomic, - flagsOffset, asize, atyp, GET_DEPS(deps))) - .value(); - if (!(GENMC_OPEN_FMODE(flags.get()) & GENMC_FMODE_WRITE)) { - handleSystemError(SystemError::SE_EBADF, "File not open for writing in write()"); - return SVal(-1); - } - - /* Fetch the inode */ - auto fileInode = GET_FILE_INODE_ADDR(file); - auto *inode = - (void *)CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::Monotonic, - fileInode, getTypeSize(intPtrType), - AType::Pointer, GET_DEPS(deps))) - .value() - .get(); - - /* Since we are writing, we need to lock of the inode */ - auto inodeLock = GET_INODE_LOCK_ADDR(inode); - handleLock(inodeLock, asize, &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return SVal(42); // lock acquisition failed - } - - SVal ret = SVal(0); - SVal wOffset, wCount; - - wCount = executeWriteChecksFS(inode, intTyp, flags, offset, count, wOffset, deps); - if (wCount.getSigned() <= 0) - goto out; - - ret = executeBufferedWriteFS(inode, intTyp, buf, bufElemTyp, wOffset, wCount, deps); - -out: - /* Release inode's lock */ - handleUnlock(inodeLock, asize, &*deps); - - /* Check for O_DSYNC/O_SYNC if write was performed */ - if (ret.getSigned() > 0) { - if (flags.get() & GENMC_O_SYNC) - executeFsyncFS(inode, intTyp); - } - return ret; -} - -void Interpreter::callWriteFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - GenericValue *buf = (GenericValue *)GVTOP(ArgVals[1]); - SVal count = ArgVals[2].IntVal.getLimitedValue(); - Type *bufElemTyp = Type::getInt8Ty(F->getContext()); - Type *intTyp = F->getFunctionType()->getParamType(0); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* We get the address of the file description, from which we will get - * the writing offset, as well as the address of the inode. */ - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in write()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* First, we must get the file's lock. If we fail to acquire the lock, - * we reset the EE to this instruction */ - auto fileLock = GET_FILE_POS_LOCK_ADDR(file); - handleLock(fileLock, asize, &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - /* Now we can read the offset at which we will try to write... */ - auto fileOffset = GET_FILE_OFFSET_ADDR(file); - auto offset = CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, GET_DEPS(deps))) - .value(); - - /* Perform the disk write operation -- may not succeed - * (If we failed to acquire the node's lock, block without returning anything) */ - auto nw = executeWriteFS(file, intTyp, buf, bufElemTyp, offset, count, deps); - if (nw.getSigned() == 42) - return; // SPECIAL CASE: lock acquisition failed - - /* If the write succeeded, we update the offset in the file description... */ - if (nw.getSigned() >= 0) { - offset += nw; - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, offset, GET_DEPS(deps))); - } - - /* We release the file description's lock */ - handleUnlock(fileLock, asize, &*deps); - - /* Return #bytes written -- if successful, fulfills the request in full */ - returnValueToCaller(retTyp, SVAL_TO_GV(nw, retTyp)); - return; -} - -void Interpreter::executeFsyncFS(void *inode, Type *intTyp) -{ - /* No need to clear reserved blocks */ - - /* do the fsync() */ - CALL_DRIVER(handleDskFsync, - DskFsyncLabel::create(currPos(), inode, getTypeSize(MI->fsInfo.inodeTyp))); - return; -} - -void Interpreter::callFsyncFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in fsync()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - auto fileInode = GET_FILE_INODE_ADDR(file); - auto *inode = (void *)CALL_DRIVER( - handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::Monotonic, - fileInode, getTypeSize(retTyp->getPointerTo()), - AType::Pointer, GET_DEPS(deps))) - .value() - .get(); - executeFsyncFS(inode, retTyp); - - returnValueToCaller(retTyp, INT_TO_GV(retTyp, 0)); - return; -} - -void Interpreter::callSyncFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - CALL_DRIVER(handleDskSync, DskSyncLabel::create(currPos())); - return; -} - -void Interpreter::callPreadFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - GenericValue *buf = (GenericValue *)GVTOP(ArgVals[1]); - SVal count = ArgVals[2].IntVal.getLimitedValue(); - SVal offset = ArgVals[3].IntVal.getLimitedValue(); - Type *bufElemTyp = Type::getInt8Ty(F->getContext()); - Type *intTyp = F->getFunctionType()->getParamType(0); - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* Check if the given offset is valid */ - if (offset.getSigned() < 0) { - handleSystemError(SystemError::SE_EINVAL, "Invalid offset in pread()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* We get the address of the file description, from which we will get - * the reading offset. In contrast to read(), we do not get the offset's lock */ - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in pread()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* Execute the read in the specified offset */ - auto nr = executeReadFS(file, intTyp, buf, bufElemTyp, offset, count, deps); - if (getCurThr().isBlocked()) - return; - - /* Return the number of bytes read (similar to read()) */ - returnValueToCaller(retTyp, SVAL_TO_GV(nr, retTyp)); - return; -} - -void Interpreter::callPwriteFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - GenericValue *buf = (GenericValue *)GVTOP(ArgVals[1]); - SVal count = ArgVals[2].IntVal.getLimitedValue(); - SVal offset = ArgVals[3].IntVal.getLimitedValue(); - Type *bufElemTyp = Type::getInt8Ty(F->getContext()); - Type *intTyp = F->getFunctionType()->getParamType(0); - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* Check if the given offset is valid */ - if (offset.getSigned() < 0) { - handleSystemError(SystemError::SE_EINVAL, "Invalid offset in pwrite()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* We get the address of the file description, from which we will get - * the reading offset. In contrast to write(), we do not get the offset's lock */ - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in pwrite()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* Execute the write in the specified offset */ - auto nw = executeWriteFS(file, intTyp, buf, bufElemTyp, offset, count, deps); - - /* Return the number of bytes written */ - returnValueToCaller(retTyp, SVAL_TO_GV(nw, retTyp)); - return; -} - -SVal Interpreter::executeLseekFS(void *file, Type *intTyp, SVal offset, SVal whence, - const std::unique_ptr &deps) -{ - Type *intPtrType = intTyp->getPointerTo(); - auto asize = getTypeSize(intTyp); - auto atyp = TYPE_TO_ATYPE(intTyp); - - /* We get the address of the inode (to read isize, as in ext4_llseek) */ - auto fileInode = GET_FILE_INODE_ADDR(file); - auto *inode = - (void *)CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::Monotonic, - fileInode, getTypeSize(intPtrType), - AType::Pointer, GET_DEPS(deps))) - .value() - .get(); - - /* We read the inode size before switching on WHENCE */ - auto fileSize = readInodeSizeFS(inode, intTyp, deps); - - /* Then, we calculate the new offset before updating it */ - SVal newOffset; - auto fileOffset = GET_FILE_OFFSET_ADDR(file); - switch (whence.get()) { - case GENMC_SEEK_SET: - newOffset = offset; - break; - case GENMC_SEEK_END: - newOffset = offset; - newOffset += fileSize; - break; - case GENMC_SEEK_CUR: { - if (offset.get() == 0) { - /* Special case: Position-querying operation */ - return CALL_DRIVER( - handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, GET_DEPS(deps))) - .value(); - } - - /* This case is weird in the kernel: The offset is updated while holding - * f_lock (as opposed to f_pos_lock), but I think this is a leftover from - * some previous version, where only SEEK_CURs would synchronize. Now, - * since we hold f_pos_lock anyway, getting f_lock as well seems - * unnecessary, at least for our purposes. - * - * In any case, the update is performed within the switch statement, - * as is done in the kernel. */ - newOffset = - CALL_DRIVER(handleLoad, - ReadLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, GET_DEPS(deps))) - .value(); - newOffset += offset; - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, - fileOffset, asize, atyp, newOffset.get(), - GET_DEPS(deps))); - return newOffset; - } - default: - handleSystemError(SystemError::SE_EINVAL, "whence is not valid in lseek()"); - newOffset = SVal(-1); // signed - return newOffset; - } - /* Update the offset (if lseek has not already returned) */ - CALL_DRIVER(handleStore, - WriteLabel::create(currPos(), llvm::AtomicOrdering::NotAtomic, fileOffset, - asize, atyp, newOffset.get(), GET_DEPS(deps))); - return newOffset; -} - -void Interpreter::callLseekFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - GenericValue fd = ArgVals[0]; - SVal offset = ArgVals[1].IntVal.getLimitedValue(); - SVal whence = ArgVals[2].IntVal.getLimitedValue(); - Type *intTyp = F->getFunctionType()->getParamType(0); - Type *retTyp = F->getReturnType(); - - getCurThr().takeSnapshot(); - auto deps = makeEventDeps(nullptr, nullptr, getCtrlDeps(getCurThr().id), - getAddrPoDeps(getCurThr().id), nullptr); - - /* We get the address of the file description, from which we will get - * the offset to modify */ - auto *file = getFileFromFd(fd.IntVal.getLimitedValue()); - if (!file) { - handleSystemError(SystemError::SE_EBADF, "File is not open in lseek()"); - returnValueToCaller(retTyp, INT_TO_GV(retTyp, -1)); - return; - } - - /* First, we must get the file's lock. If we fail to acquire the lock, - * we reset the EE to this instruction */ - auto *fileLock = GET_FILE_POS_LOCK_ADDR(file); - handleLock(fileLock, getTypeSize(intTyp), &*deps); - if (getCurThr().isBlocked()) { - getCurThr().rollToSnapshot(); - return; - } - - auto newOffset = executeLseekFS(file, intTyp, offset, whence, deps); - - /* We release the file description's lock */ - handleUnlock(fileLock, getTypeSize(intTyp), &*deps); - returnValueToCaller(retTyp, SVAL_TO_GV(newOffset, retTyp)); - return; -} - -void Interpreter::callPersBarrierFS(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - CALL_DRIVER(handleDskPbarrier, DskPbarrierLabel::create(currPos())); - return; -} - -bool isInternalCall(Function *F) { return internalFunNames.count(F->getName().str()); } - -bool isInvalidRecCall(InternalFunctions fCode, const std::vector &ArgVals) -{ - return isFsInvalidRecCode(fCode) || (fCode == InternalFunctions::FN_OpenFS && - (ArgVals[1].IntVal.getLimitedValue() & GENMC_O_CREAT)); -} - -#define CALL_INTERNAL_FUNCTION(NAME) \ - case InternalFunctions::FN_##NAME: \ - call##NAME(F, ArgVals, specialDeps); \ - break - -void Interpreter::callInternalFunction(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - auto fCode = internalFunNames.at(F->getName().str()); - - /* Make sure we are not trying to make an invalid call during recovery */ - if (getProgramState() == ProgramState::Recovery && isInvalidRecCall(fCode, ArgVals)) { - driver->reportError(currPos(), VerificationError::VE_InvalidRecoveryCall, - F->getName().str() + "() cannot be called during recovery"); - return; - } - - switch (fCode) { - CALL_INTERNAL_FUNCTION(AssertFail); - CALL_INTERNAL_FUNCTION(OptBegin); - CALL_INTERNAL_FUNCTION(LoopBegin); - CALL_INTERNAL_FUNCTION(SpinStart); - CALL_INTERNAL_FUNCTION(SpinEnd); - CALL_INTERNAL_FUNCTION(FaiZNESpinEnd); - CALL_INTERNAL_FUNCTION(LockZNESpinEnd); - CALL_INTERNAL_FUNCTION(KillThread); - CALL_INTERNAL_FUNCTION(Assume); - CALL_INTERNAL_FUNCTION(NondetInt); - CALL_INTERNAL_FUNCTION(Malloc); - CALL_INTERNAL_FUNCTION(MallocAligned); - CALL_INTERNAL_FUNCTION(PMalloc); - CALL_INTERNAL_FUNCTION(Free); - CALL_INTERNAL_FUNCTION(ThreadSelf); - CALL_INTERNAL_FUNCTION(ThreadCreate); - CALL_INTERNAL_FUNCTION(ThreadCreateSymmetric); - CALL_INTERNAL_FUNCTION(ThreadJoin); - CALL_INTERNAL_FUNCTION(ThreadExit); - CALL_INTERNAL_FUNCTION(AtExit); - CALL_INTERNAL_FUNCTION(MutexInit); - CALL_INTERNAL_FUNCTION(MutexLock); - CALL_INTERNAL_FUNCTION(MutexUnlock); - CALL_INTERNAL_FUNCTION(MutexTrylock); - CALL_INTERNAL_FUNCTION(MutexDestroy); - CALL_INTERNAL_FUNCTION(BarrierInit); - CALL_INTERNAL_FUNCTION(BarrierWait); - CALL_INTERNAL_FUNCTION(BarrierDestroy); - CALL_INTERNAL_FUNCTION(HazptrAlloc); - CALL_INTERNAL_FUNCTION(HazptrProtect); - CALL_INTERNAL_FUNCTION(HazptrClear); - CALL_INTERNAL_FUNCTION(HazptrFree); - CALL_INTERNAL_FUNCTION(HazptrRetire); - CALL_INTERNAL_FUNCTION(OpenFS); - CALL_INTERNAL_FUNCTION(CreatFS); - CALL_INTERNAL_FUNCTION(CloseFS); - CALL_INTERNAL_FUNCTION(RenameFS); - CALL_INTERNAL_FUNCTION(LinkFS); - CALL_INTERNAL_FUNCTION(UnlinkFS); - CALL_INTERNAL_FUNCTION(TruncateFS); - CALL_INTERNAL_FUNCTION(ReadFS); - CALL_INTERNAL_FUNCTION(WriteFS); - CALL_INTERNAL_FUNCTION(FsyncFS); - CALL_INTERNAL_FUNCTION(SyncFS); - CALL_INTERNAL_FUNCTION(PreadFS); - CALL_INTERNAL_FUNCTION(PwriteFS); - CALL_INTERNAL_FUNCTION(LseekFS); - CALL_INTERNAL_FUNCTION(PersBarrierFS); - CALL_INTERNAL_FUNCTION(SmpFenceLKMM); - CALL_INTERNAL_FUNCTION(RCUReadLockLKMM); - CALL_INTERNAL_FUNCTION(RCUReadUnlockLKMM); - CALL_INTERNAL_FUNCTION(SynchronizeRCULKMM); - CALL_INTERNAL_FUNCTION(CLFlush); - default: - BUG(); - break; - } - return; -} - -std::vector -Interpreter::translateExternalCallArgs(Function *F, const std::vector &ArgVals) const -{ - std::vector result; - - for (auto i = 0u; i < ArgVals.size(); ++i) { - /* Unfortunately, we cannot check for the F->arg_begin() type: - * the signature for printf might contain var_args (and thus it might be - * distance(arg_begin(), arg_end()) < ArgVals.size()), so we just - * check whether .PointerVal is non-null and hope for the best */ - if (GVTOP(ArgVals[i]) && SAddr(GVTOP(ArgVals[i])).isStatic()) { - auto transAddr = PTOGV(getStaticAddr(GVTOP(ArgVals[i]))); - result.push_back(transAddr); - } else { - result.push_back(ArgVals[i]); - } - } - return result; -} - -//===----------------------------------------------------------------------===// -// callFunction - Execute the specified function... -// -void Interpreter::callFunction(Function *F, const std::vector &ArgVals, - const std::unique_ptr &specialDeps) -{ - /* Special handling for internal calls */ - if (isInternalCall(F)) { - callInternalFunction(F, ArgVals, specialDeps); - return; - } - - assert(!specialDeps); - assert((ECStack().empty() || !&ECStack().back().Caller || - ECStack().back().Caller.arg_size() == ArgVals.size()) && - "Incorrect number of arguments passed into function call!"); - // Make a new stack frame... and fill it in. - ECStack().push_back(ExecutionContext()); - - ExecutionContext &StackFrame = ECStack().back(); - StackFrame.CurFunction = F; - - // Special handling for external functions. - if (F->isDeclaration()) { - auto translated = translateExternalCallArgs(F, ArgVals); - auto Result = callExternalFunction(F, translated); - // Simulate a 'ret' instruction of the appropriate type. - popStackAndReturnValueToCaller(F->getReturnType(), Result); - return; - } - - // Get pointers to first LLVM BB & Instruction in function. - StackFrame.CurBB = &F->front(); - StackFrame.CurInst = StackFrame.CurBB->begin(); - - // Run through the function arguments and initialize their values... - assert((ArgVals.size() == F->arg_size() || - (ArgVals.size() > F->arg_size() && F->getFunctionType()->isVarArg())) && - "Invalid number of values passed to function invocation!"); - - // Handle non-varargs arguments... - unsigned i = 0; - for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI, ++i) - SetValue(&*AI, ArgVals[i], StackFrame); - - // Handle varargs arguments... - StackFrame.VarArgs.assign(ArgVals.begin() + i, ArgVals.end()); -} - -std::string getFilenameFromMData(MDNode *node) -{ - const llvm::DILocation &loc = static_cast(*node); - llvm::StringRef file = loc.getFilename(); - llvm::StringRef dir = loc.getDirectory(); - - BUG_ON(!file.size()); - - std::string absPath; - if (file.front() == '/') { - absPath = file.str(); - } else { - BUG_ON(!dir.size()); - absPath = dir.str(); - if (absPath.back() != '/') - absPath += "/"; - absPath += file; - } - return absPath; -} - -void Interpreter::replayExecutionBefore(const VectorClock &before) -{ - reset(); - setExecState(ExecutionState::Replay); - setProgramState(ProgramState::Main); - - /* We have to replay all threads in order to get debug metadata */ - for (auto i = 0u; i < before.size(); i++) { - auto &thr = getThrById(i); - if (thr.isMain()) - thr.ECStack = mainECStack; - else - thr.ECStack = thr.initEC; - thr.prefixLOC.clear(); - thr.prefixLOC.resize(before.getMax(i) + 2); /* Grow since it can be accessed */ - scheduleThread(i); - if (thr.threadFun == recoveryRoutine) - setProgramState(ProgramState::Recovery); - /* Make sure to refetch references within the loop (invalidation danger) */ - while ((int)getCurThr().globalInstructions < before.getMax(i)) { - int snap = getCurThr().globalInstructions; - ExecutionContext &SF = ECStack().back(); - Instruction &I = *SF.CurInst++; - visit(I); - - /* Collect metadata only for global instructions */ - if (getCurThr().globalInstructions == snap) + // Don't call run; just run for one frame... + auto size = ECStack().size(); + while (ECStack().size() == size) { + if (driver->tryOptimizeScheduling(currPos())) continue; - /* If there are no metadata for this instruction, skip */ - if (!I.getMetadata("dbg")) - continue; - - /* Store relevant trace information in the appropriate spot */ - int line = I.getDebugLoc().getLine(); - std::string file = getFilenameFromMData(I.getMetadata("dbg")); - getCurThr().prefixLOC[snap + 1] = std::make_pair(line, file); - - /* If the instruction maps to more than one events, we have to fill more - * spots */ - for (auto i = snap + 2; - i <= std::min((int)getCurThr().globalInstructions, before.getMax(i)); - i++) - getCurThr().prefixLOC[i] = std::make_pair(line, file); + llvm::ExecutionContext &SF = ECStack().back(); + llvm::Instruction &I = *SF.CurInst++; + visit(I); } + // run(); } + setProgramState(oldState); } void Interpreter::run() diff --git a/src/ExternalFunctions.cpp b/src/Runtime/ExternalFunctions.cpp similarity index 97% rename from src/ExternalFunctions.cpp rename to src/Runtime/ExternalFunctions.cpp index e1f7e43..8e264a3 100644 --- a/src/ExternalFunctions.cpp +++ b/src/Runtime/ExternalFunctions.cpp @@ -44,27 +44,15 @@ #include "config.h" -#include "Error.hpp" -#include "Interpreter.h" -#if defined(HAVE_LLVM_IR_DATALAYOUT_H) -#include -#elif defined(HAVE_LLVM_DATALAYOUT_H) -#include -#endif -#if defined(HAVE_LLVM_IR_DERIVEDTYPES_H) -#include -#elif defined(HAVE_LLVM_DERIVEDTYPES_H) -#include -#endif -#if defined(HAVE_LLVM_IR_MODULE_H) -#include -#elif defined(HAVE_LLVM_MODULE_H) -#include -#endif +#include "Runtime/Interpreter.h" +#include "Support/Error.hpp" #include #include #include #include +#include +#include +#include #include #include #include diff --git a/src/Runtime/InternalFunction.def b/src/Runtime/InternalFunction.def new file mode 100644 index 0000000..5ccd88c --- /dev/null +++ b/src/Runtime/InternalFunction.def @@ -0,0 +1,257 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/*** NOTE: No include guard ***/ + +#ifndef FIRST_PURE_FUNCTION +#define FIRST_PURE_FUNCTION(num) +#endif +#ifndef HANDLE_PURE_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_PURE_FUNCTION(num, fun, name) +#else +#define HANDLE_PURE_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_PURE_FUNCTION +#define LAST_PURE_FUNCTION(num) +#endif + +#ifndef FIRST_ASSUME_FUNCTION +#define FIRST_ASSUME_FUNCTION(num) +#endif +#ifndef HANDLE_ASSUME_FUNCTION +#ifndef HANDLE_PURE_FUNCTION +#define HANDLE_ASSUME_FUNCTION(num, fun, name) +#else +#define HANDLE_ASSUME_FUNCTION(num, fun, name) HANDLE_PURE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_ASSUME_FUNCTION +#define LAST_ASSUME_FUNCTION(num) +#endif + +#ifndef FIRST_MUTEX_FUNCTION +#define FIRST_MUTEX_FUNCTION(num) +#endif +#ifndef HANDLE_MUTEX_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_MUTEX_FUNCTION(num, fun, name) +#else +#define HANDLE_MUTEX_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_MUTEX_FUNCTION +#define LAST_MUTEX_FUNCTION(num) +#endif + +#ifndef FIRST_BARRIER_FUNCTION +#define FIRST_BARRIER_FUNCTION(num) +#endif +#ifndef HANDLE_BARRIER_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_BARRIER_FUNCTION(num, fun, name) +#else +#define HANDLE_BARRIER_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_BARRIER_FUNCTION +#define LAST_BARRIER_FUNCTION(num) +#endif + +#ifndef FIRST_CONDVAR_FUNCTION +#define FIRST_CONDVAR_FUNCTION(num) +#endif +#ifndef HANDLE_CONDVAR_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_CONDVAR_FUNCTION(num, fun, name) +#else +#define HANDLE_CONDVAR_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_CONDVAR_FUNCTION +#define LAST_CONDVAR_FUNCTION(num) +#endif + +#ifndef FIRST_ALLOC_FUNCTION +#define FIRST_ALLOC_FUNCTION(num) +#endif +#ifndef HANDLE_ALLOC_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_ALLOC_FUNCTION(num, fun, name) +#else +#define HANDLE_ALLOC_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_ALLOC_FUNCTION +#define LAST_ALLOC_FUNCTION(num) +#endif + +#ifndef FIRST_FREE_FUNCTION +#define FIRST_FREE_FUNCTION(num) +#endif +#ifndef HANDLE_FREE_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_FREE_FUNCTION(num, fun, name) +#else +#define HANDLE_FREE_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_FREE_FUNCTION +#define LAST_FREE_FUNCTION(num) +#endif + +#ifndef FIRST_OTHER_FUNCTION +#define FIRST_OTHER_FUNCTION(num) +#endif +#ifndef HANDLE_OTHER_FUNCTION +#ifndef HANDLE_FUNCTION +#define HANDLE_OTHER_FUNCTION(num, fun, name) +#else +#define HANDLE_OTHER_FUNCTION(num, fun, name) HANDLE_FUNCTION(num, fun, name) +#endif +#endif +#ifndef LAST_OTHER_FUNCTION +#define LAST_OTHER_FUNCTION(num) +#endif + +/* + * Pure functions - these have no (GenMC-) observable side effects. + */ +FIRST_PURE_FUNCTION(1) +HANDLE_PURE_FUNCTION(1, "__VERIFIER_assert_fail", AssertFail) // unique error fun +HANDLE_PURE_FUNCTION(2, "__VERIFIER_opt_begin", OptBegin) +HANDLE_PURE_FUNCTION(3, "__VERIFIER_loop_begin", LoopBegin) +HANDLE_PURE_FUNCTION(4, "__VERIFIER_spin_start", SpinStart) + +FIRST_ASSUME_FUNCTION(5) +HANDLE_PURE_FUNCTION(5, "__VERIFIER_spin_end", SpinEnd) +HANDLE_PURE_FUNCTION(8, "__VERIFIER_assume", Assume) +LAST_ASSUME_FUNCTION(8) + +HANDLE_PURE_FUNCTION(6, "__VERIFIER_faiZNE_spin_end", FaiZNESpinEnd) +HANDLE_PURE_FUNCTION(7, "__VERIFIER_lockZNE_spin_end", LockZNESpinEnd) +HANDLE_PURE_FUNCTION(9, "__VERIFIER_kill_thread", KillThread) +HANDLE_PURE_FUNCTION(10, "__VERIFIER_nondet_int", NondetInt) +HANDLE_PURE_FUNCTION(11, "__VERIFIER_thread_self", ThreadSelf) +HANDLE_PURE_FUNCTION(12, "__VERIFIER_annotate_begin", AnnotateBegin) +HANDLE_PURE_FUNCTION(13, "__VERIFIER_annotate_end", AnnotateEnd) +HANDLE_PURE_FUNCTION(14, "__VERIFIER_hazptr_protect", HazptrProtect) +HANDLE_PURE_FUNCTION(15, "__VERIFIER_hazptr_clear", HazptrClear) +LAST_PURE_FUNCTION(15) + +/* + * Mutex functions - these denote some mutex operation. + * Useful to distinguish for tracking dependencies. + */ +FIRST_MUTEX_FUNCTION(16) +HANDLE_MUTEX_FUNCTION(16, "__VERIFIER_mutex_init", MutexInit) +HANDLE_MUTEX_FUNCTION(17, "__VERIFIER_mutex_lock", MutexLock) +HANDLE_MUTEX_FUNCTION(18, "__VERIFIER_mutex_unlock", MutexUnlock) +HANDLE_MUTEX_FUNCTION(19, "__VERIFIER_mutex_trylock", MutexTrylock) +HANDLE_MUTEX_FUNCTION(20, "__VERIFIER_mutex_destroy", MutexDestroy) +LAST_MUTEX_FUNCTION(20) + +/* + * Barrier functions - for barrier operations + */ +FIRST_BARRIER_FUNCTION(21) +HANDLE_BARRIER_FUNCTION(21, "__VERIFIER_barrier_init", BarrierInit) +HANDLE_BARRIER_FUNCTION(22, "__VERIFIER_barrier_wait", BarrierWait) +HANDLE_BARRIER_FUNCTION(23, "__VERIFIER_barrier_destroy", BarrierDes) +LAST_BARRIER_FUNCTION(23) + +/* + * Condvar functions - for condition variables. + */ +FIRST_CONDVAR_FUNCTION(24) +HANDLE_CONDVAR_FUNCTION(24, "__VERIFIER_cond_init", CondVarInit) +HANDLE_CONDVAR_FUNCTION(45, "__VERIFIER_cond_wait", CondVarWait) +HANDLE_CONDVAR_FUNCTION(26, "__VERIFIER_cond_signal", CondVarSignal) +HANDLE_CONDVAR_FUNCTION(27, "__VERIFIER_cond_broadcast", CondVarBcast) +HANDLE_CONDVAR_FUNCTION(28, "__VERIFIER_cond_destroy", CondVarDestroy) +LAST_CONDVAR_FUNCTION(28) + +/* + * Alloc functions - for memory allocation. + */ +FIRST_ALLOC_FUNCTION(29) +HANDLE_ALLOC_FUNCTION(29, "__VERIFIER_malloc", Malloc) +HANDLE_ALLOC_FUNCTION(30, "__VERIFIER_malloc_aligned", MallocAligned) +HANDLE_ALLOC_FUNCTION(31, "__VERIFIER_palloc", PMalloc) +HANDLE_ALLOC_FUNCTION(32, "__VERIFIER_hazptr_alloc", HazptrAlloc) +LAST_ALLOC_FUNCTION(32) + +/* + * Free functions - for memory deallocation. + */ +FIRST_FREE_FUNCTION(33) +HANDLE_FREE_FUNCTION(33, "__VERIFIER_free", Free) +HANDLE_FREE_FUNCTION(34, "__VERIFIER_hazptr_free", HazptrFree) +HANDLE_FREE_FUNCTION(35, "__VERIFIER_hazptr_retire", HazptrRetire) +LAST_FREE_FUNCTION(35) + +/* + * Other functions - other function calls (w/ side effects) + * that GenMC needs to track. + */ +FIRST_OTHER_FUNCTION(36) +HANDLE_OTHER_FUNCTION(36, "__VERIFIER_thread_create", ThreadCreate) +HANDLE_OTHER_FUNCTION(37, "__VERIFIER_thread_create_symmetric", ThreadCreateSymmetric) +HANDLE_OTHER_FUNCTION(38, "__VERIFIER_thread_join", ThreadJoin) +HANDLE_OTHER_FUNCTION(39, "__VERIFIER_thread_exit", ThreadExit) +HANDLE_OTHER_FUNCTION(40, "__VERIFIER_atexit", AtExit) +LAST_OTHER_FUNCTION(40) + +#undef FIRST_PURE_FUNCTION +#undef HANDLE_PURE_FUNCTION +#undef LAST_PURE_FUNCTION + +#undef FIRST_ASSUME_FUNCTION +#undef HANDLE_ASSUME_FUNCTION +#undef LAST_ASSUME_FUNCTION + +#undef FIRST_MUTEX_FUNCTION +#undef HANDLE_MUTEX_FUNCTION +#undef LAST_MUTEX_FUNCTION + +#undef FIRST_BARRIER_FUNCTION +#undef HANDLE_BARRIER_FUNCTION +#undef LAST_BARRIER_FUNCTION + +#undef FIRST_CONDVAR_FUNCTION +#undef HANDLE_CONDVAR_FUNCTION +#undef LAST_CONDVAR_FUNCTION + +#undef FIRST_ALLOC_FUNCTION +#undef HANDLE_ALLOC_FUNCTION +#undef LAST_ALLOC_FUNCTION + +#undef FIRST_FREE_FUNCTION +#undef HANDLE_FREE_FUNCTION +#undef LAST_FREE_FUNCTION + +#undef FIRST_OTHER_FUNCTION +#undef HANDLE_OTHER_FUNCTION +#undef LAST_OTHER_FUNCTION + +#ifdef HANDLE_FUNCTION +#undef HANDLE_FUNCTION +#endif diff --git a/src/Interpreter.cpp b/src/Runtime/Interpreter.cpp similarity index 96% rename from src/Interpreter.cpp rename to src/Runtime/Interpreter.cpp index b318c0e..908946f 100644 --- a/src/Interpreter.cpp +++ b/src/Runtime/Interpreter.cpp @@ -38,9 +38,10 @@ #include "config.h" -#include "Config.hpp" -#include "Error.hpp" +#include "Config/Config.hpp" #include "Interpreter.h" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include #include #include @@ -185,7 +186,7 @@ void Interpreter::collectStaticAddresses(SAddrAllocator &alloctor) auto *M = Modules.back().get(); std::vector> toReinitialize; - for (auto &v : M->getGlobalList()) { + for (auto &v : GLOBALS(*M)) { char *ptr = static_cast(GVTOP(getConstantValue(&v))); unsigned int typeSize = getDataLayout().getTypeAllocSize(v.getValueType()); @@ -321,14 +322,16 @@ std::unique_ptr Interpreter::updateFunArgDeps(unsigned int tid, Funct return nullptr; } - auto iFunCode = internalFunNames.at(name); - if (iFunCode == InternalFunctions::FN_Assume) { - /* We have ctrl dependency on the argument of an assume() */ + /* We have ctrl dependency on the argument of an assume() */ + if (isAssumeFunction(name)) { for (auto i = SF.Caller.arg_begin(), e = SF.Caller.arg_end(); i != e; ++i) { updateCtrlDeps(tid, *i); } - } else if (isMutexCode(iFunCode) || isBarrierCode(iFunCode)) { - /* We have addr dependency on the argument of mutex/barrier calls */ + return nullptr; + } + /* We have addr dependency on the argument of mutex/barrier/condvar calls */ + auto iFunCode = internalFunNames.at(name); + if (isMutexCode(iFunCode) || isBarrierCode(iFunCode) || isCondVarCode(iFunCode)) { return makeEventDeps(getDataDeps(tid, *SF.Caller.arg_begin()), nullptr, getCtrlDeps(tid), getAddrPoDeps(tid), nullptr); } @@ -387,19 +390,6 @@ Interpreter::Interpreter(std::unique_ptr M, std::unique_ptr Interpreter::~Interpreter() { delete IL; } -void Interpreter::runAtExitHandlers() -{ - auto oldState = getProgramState(); - setProgramState(ProgramState::Dtors); - while (!dynState.AtExitHandlers.empty()) { - scheduleThread(0); - callFunction(dynState.AtExitHandlers.back(), std::vector(), nullptr); - dynState.AtExitHandlers.pop_back(); - run(); - } - setProgramState(oldState); -} - namespace { class ArgvArray { std::unique_ptr Array; @@ -420,7 +410,11 @@ void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE, Array = std::make_unique((InputArgv.size() + 1) * PtrSize); // LLVM_DEBUG(dbgs() << "JIT: ARGV = " << (void *)Array.get() << "\n"); +#if LLVM_VERSION_MAJOR < 18 Type *SBytePtr = Type::getInt8PtrTy(C); +#else + Type *SBytePtr = PointerType::getUnqual(C); +#endif for (unsigned i = 0; i != InputArgv.size(); ++i) { unsigned Size = InputArgv[i].size() + 1; @@ -551,7 +545,11 @@ void Interpreter::setupMain(Function *Fn, const std::vector &argv, // Check main() type unsigned NumArgs = Fn->getFunctionType()->getNumParams(); FunctionType *FTy = Fn->getFunctionType(); +#if LLVM_VERSION_MAJOR < 18 Type *PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo(); +#else + Type *PPInt8Ty = PointerType::get(Fn->getContext(), 0); +#endif // Check the argument types. if (NumArgs > 3) diff --git a/src/Runtime/Interpreter.h b/src/Runtime/Interpreter.h new file mode 100644 index 0000000..c8d9b67 --- /dev/null +++ b/src/Runtime/Interpreter.h @@ -0,0 +1,828 @@ +// For the parts of the code originating from LLVM-3.5: +//===-- Interpreter.h ------------------------------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LLVMLICENSE for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines the interpreter structure +// +//===----------------------------------------------------------------------===// + +/* + * (For the parts of the code modified from LLVM-3.5) + * + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#include "config.h" + +#ifndef LLI_INTERPRETER_H +#define LLI_INTERPRETER_H + +#include "ADT/View.hpp" +#include "ADT/value_ptr.hpp" +#include "Config/Config.hpp" +#include "Runtime/DepTracker.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/ModuleInfo.hpp" +#include "Support/MemAccess.hpp" +#include "Support/SAddr.hpp" +#include "Support/SAddrAllocator.hpp" +#include "Support/SVal.hpp" +#include "Support/ThreadInfo.hpp" +#include "Verification/VerificationError.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Some helpers for GenericValues */ +#define INT_TO_GV(typ, val) \ + ({ \ + llvm::GenericValue __ret; \ + __ret.IntVal = llvm::APInt((typ)->getIntegerBitWidth(), (val), true); \ + __ret; \ + }) + +#define PTR_TO_GV(ptr) \ + ({ \ + llvm::GenericValue __ret; \ + __ret.PointerVal = (void *)(ptr); \ + __ret; \ + }) + +#define GET_ZERO_GV(typ) \ + ({ \ + llvm::GenericValue __ret; \ + if (typ->isPointerTy()) \ + __ret = PTR_TO_GV(nullptr); \ + else \ + __ret = INT_TO_GV(typ, 0); \ + __ret; \ + }) + +class GenMCDriver; + +#define INT_TO_GV(typ, val) \ + ({ \ + llvm::GenericValue __ret; \ + __ret.IntVal = llvm::APInt((typ)->getIntegerBitWidth(), (val), true); \ + __ret; \ + }) + +#define PTR_TO_GV(ptr) \ + ({ \ + llvm::GenericValue __ret; \ + __ret.PointerVal = (void *)(ptr); \ + __ret; \ + }) + +namespace llvm { + +class IntrinsicLowering; +struct FunctionInfo; +template class generic_gep_type_iterator; +class ConstantExpr; +typedef generic_gep_type_iterator gep_type_iterator; + +typedef std::vector ValuePlaneTy; + +// AllocaHolder - Object to track all of the blocks of memory allocated by +// allocas in a particular stack frame. Since the driver needs to be made +// aware of the deallocs, special care needs to be taken to inform the driver +// when stack frames are popped +// +class AllocaHolder { + std::vector allocas; + +public: + using Allocas = std::vector; + + AllocaHolder() {} + + void add(void *mem) { allocas.push_back(mem); } + const Allocas &get() const { return allocas; } +}; + +// ExecutionContext struct - This struct represents one stack frame currently +// executing. +// +struct ExecutionContext { + Function *CurFunction; // The currently executing function + BasicBlock *CurBB; // The currently executing BB + BasicBlock::iterator CurInst; // The next instruction to execute + CallInstWrapper Caller; // Holds the call that called subframes. + // NULL if main func or debugger invoked fn + std::map Values; // LLVM values used in this invocation + std::vector VarArgs; // Values passed through an ellipsis + AllocaHolder Allocas; // Track memory allocated by alloca + + ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} +}; + +/* The different reasons a thread might block */ +enum class BlockageType { + NotBlocked, + ThreadJoin, + Spinloop, + FaiZNESpinloop, + LockZNESpinloop, + HelpedCas, + Confirmation, + ReadOptBlock, + LockNotAcq, + LockNotRel, + Barrier, + Cons, + Error, + User, +}; + +/* + * Thread class -- Contains information specific to each thread. + */ +class Thread { + +public: + using MyRNG = std::minstd_rand; + using MyDist = std::uniform_int_distribution; + static constexpr int seed = 1995; + + int id; + int parentId; + llvm::Function *threadFun; + SVal threadArg; + std::vector ECStack; + std::vector initEC; + std::unordered_map tls; + unsigned int globalInstructions; + unsigned int globalInstSnap; + BasicBlock::iterator curInstSnap; + BlockageType blocked; + MyRNG rng; + std::vector> prefixLOC; + + bool isMain() const { return id == 0; } + + void block(BlockageType t) { blocked = t; } + void unblock() { blocked = BlockageType::NotBlocked; } + bool isBlocked() const { return blocked != BlockageType::NotBlocked; } + BlockageType getBlockageType() const { return blocked; } + + /* Useful for one-to-many instr->events correspondence */ + void takeSnapshot() + { + globalInstSnap = globalInstructions; + curInstSnap = --ECStack.back().CurInst; + ++ECStack.back().CurInst; + } + void rollToSnapshot() + { + globalInstructions = globalInstSnap; + ECStack.back().CurInst = curInstSnap; + } + +protected: + friend class Interpreter; + + Thread(llvm::Function *F, int id) + : id(id), parentId(-1), threadFun(F), initEC(), globalInstructions(0), + blocked(BlockageType::NotBlocked), rng(seed) + {} + + Thread(llvm::Function *F, SVal arg, int id, int pid, const llvm::ExecutionContext &SF) + : id(id), parentId(pid), threadFun(F), threadArg(arg), initEC({SF}), + globalInstructions(0), blocked(BlockageType::NotBlocked), rng(seed) + {} +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Thread &thr); + +/* Pers: The state of the program -- i.e., part of the program being interpreted */ +enum class ProgramState { Ctors, Main, Dtors, Recovery }; + +/* The state of the current execution */ +enum class ExecutionState { Normal, Replay }; + +struct DynamicComponents { + + /* Information about threads as well as the currently executing thread */ + std::vector threads; + int currentThread = 0; + + /* Pointer to the dependency tracker */ + value_ptr depTracker = nullptr; + + /* Information about the interpreter's state */ + ExecutionState execState = ExecutionState::Normal; + ProgramState programState = ProgramState::Main; /* Pers */ + + /* Pers: A map from file descriptors to file descriptions */ + llvm::IndexedMap fdToFile; + + /* Pers: Maps a filename to the address of the contents of the directory's inode for + * said name (the contents should have the address of the file's inode) */ + std::unordered_map nameToInodeAddr; + + GenericValue ExitValue; // The return value of the called function + + // AtExitHandlers - List of functions to call when the program exits, + // registered with the atexit() library function. + std::vector AtExitHandlers; +}; + +using InterpreterState = DynamicComponents; + +// Interpreter - This class represents the entirety of the interpreter. +// +class Interpreter : public ExecutionEngine, public InstVisitor { + +public: + using AnnotID = ModuleID::ID; + using AnnotT = SExpr; + +protected: + /*** Static components (once set, do not change) ***/ + + /* Information about the module under test */ + std::unique_ptr MI; + + /* List of thread-local variables, with their initializing values */ + std::unordered_map threadLocalVars; + + /* Mapping between static allocation beginning and the actual addresses of + * global variables (where their contents are stored) */ + std::unordered_map staticValueMap; + + /* Keep all static ranges that have been allocated */ + VSet> staticAllocas; + + /* Maintain the relationship between SAddr and global variables, + * so that we can get naming information */ + std::unordered_map staticNames; + + /* (Composition) pointer to the driver */ + GenMCDriver *driver; + + Function *mainFun = nullptr; + + /* Whether the driver should be called on system errors */ + bool stopOnSystemErrors; + + /* Where system errors return values should be stored (if required) */ + SAddr errnoAddr; + Type *errnoTyp; + + /* Pers: The recovery routine to run */ + Function *recoveryRoutine = nullptr; + + /* This is not exactly static but is reset to the same value each time*/ + std::vector mainECStack; + + IntrinsicLowering *IL; + + /*** Dynamic components (change during verification) ***/ + + DynamicComponents dynState; + +public: + explicit Interpreter(std::unique_ptr M, std::unique_ptr MI, + GenMCDriver *driver, const Config *userConf, SAddrAllocator &alloctor); + virtual ~Interpreter(); + + std::unique_ptr saveState(); + void restoreState(std::unique_ptr); + + Thread &constructAddThreadFromInfo(const ThreadInfo &ti) + { + auto *calledFun = + dyn_cast(const_cast(MI->idInfo.IDV.at(ti.funId))); + BUG_ON(!calledFun); + ExecutionContext SF; + + SF.CurFunction = calledFun; + SF.CurBB = &calledFun->front(); + SF.CurInst = SF.CurBB->begin(); + + SF.Values[&*calledFun->arg_begin()] = PTR_TO_GV(ti.arg.get()); + return createAddNewThread(calledFun, ti.arg, ti.id, ti.parentId, SF); + } + void setExecutionContext(const std::vector &tis) + { + dynState.threads.clear(); + createAddMainThread(); + for (auto &ti : tis) + constructAddThreadFromInfo(ti); + } + +#define CALL_DRIVER(method, ...) \ + ({ \ + if (getProgramState() != ProgramState::Recovery || #method != "handleLoad") { \ + incPos(); \ + } \ + driver->method(__VA_ARGS__); \ + }) + +/* When replaying, we don't decrease the pos so we don't get into an + * infinite loop, e.g., if the last instruction reads bottom. + * (Besides, the amount of replaying should be well-defined.) + */ +#define CALL_DRIVER_RESET_IF_NONE(method, ...) \ + ({ \ + incPos(); \ + auto ret = driver->method(__VA_ARGS__); \ + if (!ret.has_value() && getExecState() != ExecutionState::Replay) { \ + decPos(); \ + --ECStack().back().CurInst; \ + } else if (getProgramState() == ProgramState::Recovery && \ + #method == "handleLoad") { \ + decPos(); \ + } \ + ret; \ + }) + +#define CALL_DRIVER_RESET_IF_FALSE(method, ...) \ + ({ \ + incPos(); \ + auto ret = driver->method(__VA_ARGS__); \ + if (!ret) { \ + decPos(); \ + --ECStack().back().CurInst; \ + } \ + ret; \ + }) + + /* Blocks the current execution */ + void block(BlockageType t = BlockageType::Error) + { + std::for_each(threads_begin(), threads_end(), [&](Thread &thr) { thr.block(t); }); + } + + /* Resets all thread info to their initial values */ + void resetThread(unsigned int id); + + /* Resets the interpreter at the beginning of a new execution */ + void reset(); + + /* Pers: Setups the execution context for the recovery routine + * in thread TID. Assumes that the thread has already been added + * to the thread list. */ + void setupRecoveryRoutine(int tid); + + /* Pers: Does cleanups after the recovery routine has run */ + void cleanupRecoveryRoutine(int tid); + + /* Creates a new thread and adds it to the thread list */ + Thread &createAddNewThread(llvm::Function *F, SVal arg, int tid, int pid, + const llvm::ExecutionContext &SF); + + /* Pers: Creates a thread for the recovery routine and adds it to + * the thread list */ + Thread &createAddRecoveryThread(int tid); + + /* Sets-up the specified thread for execution */ + void scheduleThread(int tid) { dynState.currentThread = tid; } + + /* Returns the currently executing thread */ + Thread &getCurThr() { return dynState.threads[dynState.currentThread]; } + const Thread &getCurThr() const { return dynState.threads.at(dynState.currentThread); } + + /* Returns the thread with the specified ID (taken from the graph) */ + Thread &getThrById(int id) { return dynState.threads[id]; }; + const Thread &getThrById(int id) const { return dynState.threads[id]; }; + + unsigned int getNumThreads() const { return dynState.threads.size(); } + + using thread_iterator = std::vector::iterator; + using const_thread_iterator = std::vector::const_iterator; + using thread_range = iterator_range; + using const_thread_range = iterator_range; + + const_thread_iterator threads_begin() const { return dynState.threads.begin(); } + const_thread_iterator threads_end() const { return dynState.threads.end(); } + thread_iterator threads_begin() { return dynState.threads.begin(); } + thread_iterator threads_end() { return dynState.threads.end(); } + const_thread_range threads() const + { + return const_thread_range(threads_begin(), threads_end()); + } + thread_range threads() { return thread_range(threads_begin(), threads_end()); } + + /* Returns the stack frame of the currently executing thread */ + std::vector &ECStack() { return getCurThr().ECStack; } + + /* Returns the current (global) position (thread, index) interpreted */ + Event currPos() const { return Event(getCurThr().id, getCurThr().globalInstructions); }; + Event nextPos() const { return currPos().next(); }; + Event incPos() + { + auto &thr = getCurThr(); + return Event(thr.id, ++thr.globalInstructions); + }; + Event decPos() + { + auto &thr = getCurThr(); + return Event(thr.id, --thr.globalInstructions); + }; + + /* Query interpreter's state */ + ProgramState getProgramState() const { return dynState.programState; } + ExecutionState getExecState() const { return dynState.execState; } + + /* Annotation information */ + + /* Returns annotation information for the instruction I */ + const AnnotT *getAnnotation(Instruction *I) const + { + auto id = MI->idInfo.VID[I]; + return MI->annotInfo.annotMap.count(id) ? MI->annotInfo.annotMap.at(id).get() + : nullptr; + } + + /* Returns (concretized) annotation information for the + * current instruction (assuming we're executing it) */ + std::unique_ptr getCurrentAnnotConcretized(); + + /* Memory pools checks */ + + /* Returns true if the interpreter has allocated space for the specified static */ + bool isStaticallyAllocated(SAddr addr) const; + void *getStaticAddr(SAddr addr) const; + std::string getStaticName(SAddr addr) const; + + /// runAtExitHandlers - Run any functions registered by the program's calls to + /// atexit(3), which we intercept and store in AtExitHandlers. + /// + void runAtExitHandlers(); + + /// create - Create an interpreter ExecutionEngine. This can never fail. + /// + static std::unique_ptr + create(std::unique_ptr M, std::unique_ptr MI, GenMCDriver *driver, + const Config *userConf, SAddrAllocator &alloctor, std::string *ErrorStr = nullptr); + + /// run - Start execution with the specified function and arguments. + /// +#ifdef LLVM_EXECUTION_ENGINE_RUN_FUNCTION_VECTOR + virtual GenericValue runFunction(Function *F, const std::vector &ArgValues); +#else + virtual GenericValue runFunction(Function *F, llvm::ArrayRef ArgValues); +#endif + + void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) + { + // FIXME: not implemented. + return nullptr; + } + + void *getPointerToNamedFunction(llvm::StringRef Name, bool AbortOnFailure = true) + { + // FIXME: not implemented. + return nullptr; + }; + + /// recompileAndRelinkFunction - For the interpreter, functions are always + /// up-to-date. + /// + void *recompileAndRelinkFunction(Function *F) { return getPointerToFunction(F); } + + /// freeMachineCodeForFunction - The interpreter does not generate any code. + /// + void freeMachineCodeForFunction(Function *F) {} + + /* Helper functions */ + void replayExecutionBefore(const VectorClock &before); + + SVal getLocInitVal(const AAccess &access) + { + GenericValue result; + + LoadValueFromMemory( + result, (llvm::GenericValue *)getStaticAddr(access.getAddr()), + IntegerType::get(Modules.back()->getContext(), access.getSize().get() * 8)); + return SVal(result.IntVal.getLimitedValue()); + } + + unsigned int getTypeSize(Type *typ) const; + SVal executeAtomicRMWOperation(SVal oldVal, SVal val, ASize size, AtomicRMWInst::BinOp op); + + // Methods used to execute code: + // Place a call on the stack + void callFunction(Function *F, const std::vector &ArgVals, + const std::unique_ptr &specialDeps); + + /* callFunction() wrappers to be called before running a function */ + void setupFunctionCall(Function *F, ArrayRef ArgValues); + void setupStaticCtorsDtors(Module &M, bool isDtors); + void setupStaticCtorsDtors(bool isDtors); + void setupMain(Function *Fn, const std::vector &argv, const char *const *envp); + + void run(); // Execute instructions until nothing left to do + + /* run() wrappers */ + int runAsMain(const std::string &main); + void runRecovery(); + + // Opcode Implementations + void visitReturnInst(ReturnInst &I); + void visitBranchInst(BranchInst &I); + void visitSwitchInst(SwitchInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + + void visitBinaryOperator(BinaryOperator &I); + void visitICmpInst(ICmpInst &I); + void visitFCmpInst(FCmpInst &I); + void visitAllocaInst(AllocaInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitPHINode(PHINode &PN) { llvm_unreachable("PHI nodes already handled!"); } + void visitTruncInst(TruncInst &I); + void visitZExtInst(ZExtInst &I); + void visitSExtInst(SExtInst &I); + void visitFPTruncInst(FPTruncInst &I); + void visitFPExtInst(FPExtInst &I); + void visitUIToFPInst(UIToFPInst &I); + void visitSIToFPInst(SIToFPInst &I); + void visitFPToUIInst(FPToUIInst &I); + void visitFPToSIInst(FPToSIInst &I); + void visitPtrToIntInst(PtrToIntInst &I); + void visitIntToPtrInst(IntToPtrInst &I); + void visitBitCastInst(BitCastInst &I); + void visitSelectInst(SelectInst &I); + + void visitCallInstWrapper(CallInstWrapper CIW); +#if LLVM_VERSION_MAJOR < 11 + void visitCallSite(CallSite CS) { visitCallInstWrapper(CallInstWrapper(CS)); } +#else + void visitCallBase(CallBase &CB) { visitCallInstWrapper(CallInstWrapper(CB)); } +#endif + void visitUnreachableInst(UnreachableInst &I); + + void visitShl(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + + void visitVAArgInst(VAArgInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitShuffleVectorInst(ShuffleVectorInst &I); + + void visitExtractValueInst(ExtractValueInst &I); + void visitInsertValueInst(InsertValueInst &I); + + void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I); + void visitAtomicRMWInst(AtomicRMWInst &I); + void visitFenceInst(FenceInst &I); + + bool isInlineAsm(CallInstWrapper CIW, std::string *asmStr); + void visitInlineAsm(CallInstWrapper CIW, const std::string &asmString); + + void visitInstruction(Instruction &I) + { + errs() << I << "\n"; + llvm_unreachable("Instruction not interpretable yet!"); + } + + GenericValue callExternalFunction(Function *F, const std::vector &ArgVals); + void exitCalled(GenericValue GV); + + void addAtExitHandler(Function *F) { dynState.AtExitHandlers.push_back(F); } + + GenericValue *getFirstVarArg() { return &(ECStack().back().VarArgs[0]); } + +private: // Helper functions + GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, gep_type_iterator E, + ExecutionContext &SF); + + // SwitchToNewBasicBlock - Start execution in a new basic block and run any + // PHI nodes in the top of the block. This is used for intraprocedural + // control flow. + // + void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); + + void *getPointerToFunction(Function *F) { return (void *)F; } + void *getPointerToBasicBlock(BasicBlock *BB) { return (void *)BB; } + + void initializeExecutionEngine() {} + void initializeExternalFunctions(); + GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); + GenericValue getOperandValue(Value *V, ExecutionContext &SF); + GenericValue executeTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeSExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeZExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, Type *Ty, + ExecutionContext &SF); + std::vector + translateExternalCallArgs(Function *F, const std::vector &Args) const; + void returnValueToCaller(Type *RetTy, GenericValue Result); + void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result, + ReturnInst *retI = nullptr); + + void handleSystemError(SystemError code, const std::string &msg); + + SVal getInodeTransStatus(void *inode, Type *intTyp); + void setInodeTransStatus(void *inode, Type *intTyp, SVal status); + SVal readInodeSizeFS(void *inode, Type *intTyp, const std::unique_ptr &deps); + void updateInodeSizeFS(void *inode, Type *intTyp, SVal newSize, + const std::unique_ptr &deps); + void updateInodeDisksizeFS(void *inode, Type *intTyp, SVal newSize, SVal ordDataBegin, + SVal ordDataEnd); + void writeDataToDisk(void *buf, int bufOffset, void *inode, int inodeOffset, int count, + Type *dataTyp, const std::unique_ptr &deps); + void readDataFromDisk(void *inode, int inodeOffset, void *buf, int bufOffset, int count, + Type *dataTyp, const std::unique_ptr &deps); + void updateDirNameInode(const std::string &name, Type *intTyp, SVal inode); + + SVal checkOpenFlagsFS(SVal &flags, Type *intTyp); + SVal executeInodeLookupFS(const std::string &name, Type *intTyp); + SVal executeInodeCreateFS(const std::string &name, Type *intTyp, + const std::unique_ptr &deps); + SVal executeLookupOpenFS(const std::string &filename, SVal &flags, Type *intTyp, + const std::unique_ptr &deps); + SVal executeOpenFS(const std::string &filename, SVal flags, SVal inode, Type *intTyp, + const std::unique_ptr &deps); + + void executeReleaseFileFS(void *fileDesc, Type *intTyp, + const std::unique_ptr &deps); + SVal executeCloseFS(SVal fd, Type *intTyp, const std::unique_ptr &deps); + SVal executeRenameFS(const std::string &oldpath, SVal oldInode, const std::string &newpath, + SVal newInode, Type *intTyp); + SVal executeLinkFS(const std::string &newpath, SVal oldInode, Type *intTyp); + SVal executeUnlinkFS(const std::string &pathname, Type *intTyp); + + SVal executeTruncateFS(SVal inode, SVal length, Type *intTyp, + const std::unique_ptr &deps); + SVal executeReadFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, + SVal count, const std::unique_ptr &deps); + void zeroDskRangeFS(void *inode, SVal start, SVal end, Type *writeIntTyp); + SVal executeWriteChecksFS(void *inode, Type *intTyp, SVal flags, SVal offset, SVal count, + SVal &wOffset, const std::unique_ptr &deps); + bool shouldUpdateInodeDisksizeFS(void *inode, Type *intTyp, SVal size, SVal offset, + SVal count, SVal &dSize); + SVal executeBufferedWriteFS(void *inode, Type *intTyp, void *buf, Type *bufElemTyp, + SVal wOffset, SVal count, + const std::unique_ptr &deps); + SVal executeWriteFS(void *file, Type *intTyp, void *buf, Type *bufElemTyp, SVal offset, + SVal count, const std::unique_ptr &deps); + SVal executeLseekFS(void *file, Type *intTyp, SVal offset, SVal whence, + const std::unique_ptr &deps); + void executeFsyncFS(void *inode, Type *intTyp); + + void setProgramState(ProgramState s) { dynState.programState = s; } + void setExecState(ExecutionState s) { dynState.execState = s; } + + void handleLock(SAddr addr, ASize size, const EventDeps *deps); + void handleUnlock(SAddr addr, ASize size, const EventDeps *deps); + + /* Custom Opcode Implementations */ +#define HANDLE_FUNCTION(NUM, FUN, NAME) \ + void call##NAME(Function *F, const std::vector &ArgVals, \ + const std::unique_ptr &specialDeps); +#include "Runtime/InternalFunction.def" + + void callInternalFunction(Function *F, const std::vector &ArgVals, + const std::unique_ptr &deps); + + void freeAllocas(const AllocaHolder &allocas); + + /* Collects the addresses (and some naming information) for all variables with + * static storage. Also calculates the starting address of the allocation pool */ + void collectStaticAddresses(SAddrAllocator &alloctor); + + /* Sets up how some errors will be reported to the user */ + void setupErrorPolicy(Module *M, const Config *userConf); + + /* Pers: Sets up information about the modeled filesystem */ + void setupFsInfo(Module *M, const Config *userConf); + + /* Adds the specified thread to the list */ + Thread &addNewThread(Thread &&thread); + + /* Creates an entry for the main() function. More information are + * filled from the execution engine when the exploration starts */ + Thread &createAddMainThread(); + + /* Dependency tracking */ + + DepTracker *getDepTracker() { return &*dynState.depTracker; } + const DepTracker *getDepTracker() const { return &*dynState.depTracker; } + + std::unique_ptr makeEventDeps(const DepInfo *addr, const DepInfo *data, + const DepInfo *ctrl, const DepInfo *addrPo, + const DepInfo *cas); + + const DepInfo *getDataDeps(unsigned int tid, Value *i) + { + return getDepTracker() ? getDepTracker()->getDataDeps(tid, i) : nullptr; + } + const DepInfo *getAddrPoDeps(unsigned int tid) + { + return getDepTracker() ? getDepTracker()->getAddrPoDeps(tid) : nullptr; + } + const DepInfo *getCtrlDeps(unsigned int tid) + { + return getDepTracker() ? getDepTracker()->getCtrlDeps(tid) : nullptr; + } + + void updateDataDeps(unsigned int tid, Value *dst, Value *src) + { + if (getDepTracker()) + getDepTracker()->updateDataDeps(tid, dst, src); + } + void updateDataDeps(unsigned int tid, Value *dst, const DepInfo *e) + { + if (getDepTracker()) + getDepTracker()->updateDataDeps(tid, dst, *e); + } + void updateDataDeps(unsigned int tid, Value *dst, Event e) + { + if (getDepTracker()) + getDepTracker()->updateDataDeps(tid, dst, e); + } + void updateAddrPoDeps(unsigned int tid, Value *src) + { + if (getDepTracker()) + getDepTracker()->updateAddrPoDeps(tid, src); + } + void updateCtrlDeps(unsigned int tid, Value *src) + { + if (getDepTracker()) + getDepTracker()->updateCtrlDeps(tid, src); + } + void updateCtrlDeps(unsigned int tid, Event e) + { + if (getDepTracker()) + getDepTracker()->updateCtrlDeps(tid, e); + } + + std::unique_ptr updateFunArgDeps(unsigned int tid, Function *F); + void updateInternalFunRetDeps(unsigned int tid, Function *F, Instruction *CS); + + void clearDeps(unsigned int tid) + { + if (getDepTracker()) + getDepTracker()->clearDeps(tid); + } + + /* Gets naming information for value V (or value with key KEY), if it is + * an internal variable with no value correspondence */ + const NameInfo *getVarNameInfo(Value *v, StorageDuration sd, AddressSpace spc, + const VariableInfo::InternalKey &key = {}); + + /* Pers: Returns the address of the file description referenced by FD */ + void *getFileFromFd(int fd) const; + + /* Pers: Tracks that the address of the file description of FD is FILEADDR */ + void setFdToFile(int fd, void *fileAddr); + + /* Pers: Directory operations */ + void *getDirInode() const; + void *getInodeAddrFromName(const std::string &filename) const; +}; + +} // namespace llvm + +#endif diff --git a/src/Runtime/InterpreterEnumAPI.cpp b/src/Runtime/InterpreterEnumAPI.cpp new file mode 100644 index 0000000..e393240 --- /dev/null +++ b/src/Runtime/InterpreterEnumAPI.cpp @@ -0,0 +1,31 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#include "InterpreterEnumAPI.hpp" +#include "Support/Error.hpp" + +const std::unordered_map internalFunNames = { +#define HANDLE_FUNCTION(NUM, FUN, NAME) {FUN, InternalFunctions::NAME}, +#include "Runtime/InternalFunction.def" + + /* Some extra C++ calls */ + {"_Znwm", InternalFunctions::Malloc}, + {"_ZdlPv", InternalFunctions::Free}, +}; diff --git a/src/InterpreterEnumAPI.hpp b/src/Runtime/InterpreterEnumAPI.hpp similarity index 50% rename from src/InterpreterEnumAPI.hpp rename to src/Runtime/InterpreterEnumAPI.hpp index 75d7f19..3c6961f 100644 --- a/src/InterpreterEnumAPI.hpp +++ b/src/Runtime/InterpreterEnumAPI.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __INTERPRETER_ENUM_API_HPP__ -#define __INTERPRETER_ENUM_API_HPP__ +#ifndef GENMC_INTERPRETER_ENUM_API_HPP +#define GENMC_INTERPRETER_ENUM_API_HPP #include #include @@ -38,81 +38,10 @@ enum class StorageDuration { SD_Static, SD_Automatic, SD_Heap, SD_StorageLast }; /* Storage types */ enum class StorageType { ST_Volatile, ST_Durable, ST_StorageLast }; -/* Modeled functions -- (CAUTION: Order matters) */ +/* Modeled functions */ enum class InternalFunctions { - FN_AssertFail, - FN_OptBegin, - FN_LoopBegin, - FN_SpinStart, - - FN_SpinEnd, - FN_FaiZNESpinEnd, - FN_LockZNESpinEnd, - FN_Assume, - /* Assume calls */ - - FN_KillThread, - FN_NondetInt, - FN_ThreadSelf, - FN_AnnotateBegin, - FN_AnnotateEnd, - FN_HazptrProtect, - FN_HazptrClear, - FN_NoSideEffectsLast, - /* No side effects */ - - FN_ThreadCreate, - FN_ThreadCreateSymmetric, - FN_ThreadJoin, - FN_ThreadExit, - FN_AtExit, - FN_Malloc, - FN_MallocAligned, - FN_PMalloc, - FN_HazptrAlloc, - FN_MallocLast, - FN_Free, - FN_HazptrFree, - FN_HazptrRetire, - FN_MutexInit, - FN_MutexLock, - FN_MutexUnlock, - FN_MutexTrylock, - FN_MutexDestroy, - FN_BarrierInit, - FN_BarrierWait, - FN_BarrierDestroy, - - FN_OpenFS, - FN_CreatFS, - FN_RenameFS, - FN_LinkFS, - FN_UnlinkFS, - FN_TruncateFS, - FN_LastInodeFS, - /* Inode ops */ - FN_WriteFS, - FN_PwriteFS, - FN_PersBarrierFS, - FN_LastInvRecFS, - /* Invalid FS rec ops */ - FN_ReadFS, - FN_PreadFS, - FN_FsyncFS, - FN_SyncFS, - FN_LseekFS, - FN_CloseFS, - FN_LastFS, - /* FS ops */ - - FN_SmpFenceLKMM, - FN_RCUReadLockLKMM, - FN_RCUReadUnlockLKMM, - FN_SynchronizeRCULKMM, - /* LKMM ops */ - - FN_CLFlush, - /* Pers ops */ +#define HANDLE_FUNCTION(NUM, FUN, NAME) NAME = NUM, +#include "Runtime/InternalFunction.def" }; extern const std::unordered_map internalFunNames; @@ -124,15 +53,23 @@ inline bool isCleanInternalFunction(const std::string &name) if (!isInternalFunction(name)) return false; - auto &code = internalFunNames.at(name); - return code >= InternalFunctions::FN_AssertFail && - code <= InternalFunctions::FN_NoSideEffectsLast; + auto code = + static_cast>(internalFunNames.at(name)); + return +#define FIRST_PURE_FUNCTION(NUM) code >= NUM && +#define LAST_PURE_FUNCTION(NUM) code <= NUM; +#include "Runtime/InternalFunction.def" } inline bool isErrorFunction(const std::string &name) { return isInternalFunction(name) && - internalFunNames.at(name) == InternalFunctions::FN_AssertFail; + internalFunNames.at(name) == InternalFunctions::AssertFail; +} + +inline bool isSpinEndFunction(const std::string &name) +{ + return isInternalFunction(name) && internalFunNames.at(name) == InternalFunctions::SpinEnd; } inline bool isAssumeFunction(const std::string &name) @@ -140,8 +77,12 @@ inline bool isAssumeFunction(const std::string &name) if (!isInternalFunction(name)) return false; - auto &code = internalFunNames.at(name); - return code >= InternalFunctions::FN_SpinEnd && code <= InternalFunctions::FN_Assume; + auto code = + static_cast>(internalFunNames.at(name)); + return +#define FIRST_ASSUME_FUNCTION(NUM) code >= NUM && +#define LAST_ASSUME_FUNCTION(NUM) code <= NUM; +#include "Runtime/InternalFunction.def" } inline bool isAllocFunction(const std::string &name) @@ -149,36 +90,39 @@ inline bool isAllocFunction(const std::string &name) if (!isInternalFunction(name)) return false; - auto &code = internalFunNames.at(name); - return code >= InternalFunctions::FN_Malloc && code <= InternalFunctions::FN_MallocLast; + auto code = + static_cast>(internalFunNames.at(name)); + return +#define FIRST_ALLOC_FUNCTION(NUM) code >= NUM && +#define LAST_ALLOC_FUNCTION(NUM) code <= NUM; +#include "Runtime/InternalFunction.def" } inline bool isMutexCode(InternalFunctions code) { - return (code >= InternalFunctions::FN_MutexInit && - code <= InternalFunctions::FN_MutexDestroy); + auto codeI = static_cast>(code); + return +#define FIRST_MUTEX_FUNCTION(NUM) codeI >= NUM && +#define LAST_MUTEX_FUNCTION(NUM) codeI <= NUM; +#include "Runtime/InternalFunction.def" } inline bool isBarrierCode(InternalFunctions code) { - return (code >= InternalFunctions::FN_BarrierInit && - code <= InternalFunctions::FN_BarrierDestroy); -} - -inline bool isFsCode(InternalFunctions code) -{ - return (code >= InternalFunctions::FN_OpenFS && code <= InternalFunctions::FN_LastFS); -} - -inline bool isFsInodeCode(InternalFunctions code) -{ - return (code >= InternalFunctions::FN_OpenFS && code <= InternalFunctions::FN_LastInodeFS); + auto codeI = static_cast>(code); + return +#define FIRST_BARRIER_FUNCTION(NUM) codeI >= NUM && +#define LAST_BARRIER_FUNCTION(NUM) codeI <= NUM; +#include "Runtime/InternalFunction.def" } -inline bool isFsInvalidRecCode(InternalFunctions code) +inline bool isCondVarCode(InternalFunctions code) { - return (code >= InternalFunctions::FN_CreatFS && - code <= InternalFunctions::FN_LastInvRecFS); + auto codeI = static_cast>(code); + return +#define FIRST_CONDVAR_FUNCTION(NUM) codeI >= NUM && +#define LAST_CONDVAR_FUNCTION(NUM) codeI <= NUM; +#include "Runtime/InternalFunction.def" } inline bool hasGlobalLoadSemantics(const std::string &name) @@ -187,9 +131,9 @@ inline bool hasGlobalLoadSemantics(const std::string &name) return false; using IF = InternalFunctions; - auto &code = internalFunNames.at(name); - return code == IF::FN_MutexLock || code == IF::FN_MutexTrylock || - code == IF::FN_BarrierWait || isFsCode(code); + auto code = internalFunNames.at(name); + return code == IF::MutexLock || code == IF::MutexTrylock || code == IF::BarrierWait || + code == IF::CondVarWait; } /* Should match our internal definitions */ @@ -206,4 +150,4 @@ inline bool hasGlobalLoadSemantics(const std::string &name) #define GENMC_ATTR(flags) ((flags) & (0x0000ffff)) #define GENMC_KIND(flags) ((flags) & (0xffff0000)) -#endif /* __INTERPRETER_ENUM_API_HPP__ */ +#endif /* GENMC_INTERPRETER_ENUM_API_HPP */ diff --git a/src/SCDriver.cpp b/src/SCDriver.cpp deleted file mode 100644 index b919519..0000000 --- a/src/SCDriver.cpp +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "SCDriver.hpp" -#include "ModuleInfo.hpp" - -SCDriver::SCDriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) - : GenMCDriver(conf, std::move(mod), std::move(MI), mode) -{} - -void SCDriver::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -View SCDriver::calculate0(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -void SCDriver::visitCalc1_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitCalc1_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_0(pLab, calcRes); - } - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitCalc1_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::left; -} - -View SCDriver::calculate1(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc1_0.clear(); - visitedCalc1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_1.clear(); - visitedCalc1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_2.clear(); - visitedCalc1_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc1_1(lab, calcRes); - return calcRes; -} -std::vector> SCDriver::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector SCDriver::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - views.push_back(calculate1(lab)); - return std::move(views); -} - -void SCDriver::updateMMViews(EventLabel *lab) -{ - lab->setCalculated(calculateSaved(lab)); - lab->setViews(calculateViews(lab)); - lab->setPrefixView(calculatePrefixView(lab)); -} - -bool SCDriver::isDepTracking() const { return 0; } - -bool SCDriver::visitInclusionLHS0_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab0 = lab; - return false; - } - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS0_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS0_0(pLab, v)) - return false; - } - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::checkInclusion0(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS0_0.clear(); - visitedInclusionLHS0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS0_1.clear(); - visitedInclusionLHS0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS0_1(lab, v); -} - -void SCDriver::visitInclusionLHS1_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept1[lab->getStamp().get()] = true; - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitInclusionLHS1_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::left; -} - -bool SCDriver::checkInclusion1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0.clear(); - visitedInclusionLHS1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS1_1.clear(); - visitedInclusionLHS1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept1.clear(); - lhsAccept1.resize(g.getMaxStamp().get() + 1, false); - rhsAccept1.clear(); - rhsAccept1.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS1_1(lab); - for (auto i = 0u; i < lhsAccept1.size(); i++) { - if (lhsAccept1[i] && !rhsAccept1[i]) { - racyLab1 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool SCDriver::visitInclusionLHS2_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab2 = lab; - return false; - } - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS2_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS2_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_1(pLab, v)) - return false; - } - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::checkInclusion2(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS2_0.clear(); - visitedInclusionLHS2_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_1.clear(); - visitedInclusionLHS2_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_2.clear(); - visitedInclusionLHS2_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS2_2(lab, v); -} - -void SCDriver::visitInclusionLHS3_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept3[lab->getStamp().get()] = true; - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitInclusionLHS3_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { - auto status = visitedInclusionLHS3_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_0(pLab); - } - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitInclusionLHS3_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS3_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_1(pLab); - } - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool SCDriver::checkInclusion3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0.clear(); - visitedInclusionLHS3_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_1.clear(); - visitedInclusionLHS3_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_2.clear(); - visitedInclusionLHS3_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept3.clear(); - lhsAccept3.resize(g.getMaxStamp().get() + 1, false); - rhsAccept3.clear(); - rhsAccept3.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS3_2(lab); - for (auto i = 0u; i < lhsAccept3.size(); i++) { - if (lhsAccept3[i] && !rhsAccept3[i]) { - racyLab3 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool SCDriver::visitInclusionLHS4_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab4 = lab; - return false; - } - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS4_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS4_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS4_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_1(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::checkInclusion4(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS4_0.clear(); - visitedInclusionLHS4_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_1.clear(); - visitedInclusionLHS4_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_2.clear(); - visitedInclusionLHS4_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS4_2(lab, v); -} - -void SCDriver::visitInclusionLHS5_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept5[lab->getStamp().get()] = true; - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitInclusionLHS5_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedInclusionLHS5_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_0(pLab); - } - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::left; -} - -void SCDriver::visitInclusionLHS5_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && - llvm::dyn_cast(lab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(lab))) - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS5_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_1(pLab); - } - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool SCDriver::checkInclusion5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0.clear(); - visitedInclusionLHS5_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_1.clear(); - visitedInclusionLHS5_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_2.clear(); - visitedInclusionLHS5_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept5.clear(); - lhsAccept5.resize(g.getMaxStamp().get() + 1, false); - rhsAccept5.clear(); - rhsAccept5.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS5_2(lab); - for (auto i = 0u; i < lhsAccept5.size(); i++) { - if (lhsAccept5[i] && !rhsAccept5[i]) { - racyLab5 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool SCDriver::visitInclusionLHS6_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab6 = lab; - return false; - } - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS6_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::checkInclusion6(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS6_0.clear(); - visitedInclusionLHS6_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS6_1.clear(); - visitedInclusionLHS6_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS6_1(lab, v); -} - -bool SCDriver::visitInclusionLHS7_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab7 = lab; - return false; - } - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::visitInclusionLHS7_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS7_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS7_0(pLab, v)) - return false; - } - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool SCDriver::checkInclusion7(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS7_0.clear(); - visitedInclusionLHS7_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS7_1.clear(); - visitedInclusionLHS7_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS7_1(lab, v); -} - -VerificationError SCDriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const -{ - if (!checkInclusion0(lab)) { - race = racyLab0; - return VerificationError::VE_AccessNonMalloc; - } - - if (!checkInclusion1(lab)) { - race = racyLab1; - return VerificationError::VE_DoubleFree; - } - - if (!checkInclusion2(lab)) { - race = racyLab2; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion3(lab)) { - race = racyLab3; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion4(lab)) { - race = racyLab4; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion5(lab)) { - race = racyLab5; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion6(lab)) { - race = racyLab6; - return VerificationError::VE_RaceNotAtomic; - } - - return VerificationError::VE_OK; -} - -std::vector -SCDriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const -{ - std::vector result; - - if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkInclusion7(lab)) { - racyLabs.push_back(racyLab7); - result.push_back(VerificationError::VE_WWRace); - } - - return result; -} - -bool SCDriver::visitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - ++visitedAccepting0; - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = tc_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - --visitedAccepting0; - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool SCDriver::isAcyclic0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - if (!shouldVisitAcyclic0()) - return true; - - visitedAccepting0 = 0; - visitedAcyclic0_0.clear(); - visitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic0_0(lab); -} - -bool SCDriver::isConsistent(const EventLabel *lab) const { return true && isAcyclic0(lab); } - -bool SCDriver::isRecAcyclic(const EventLabel *lab) const -{ - visitedRecAccepting = 0; - return true; -} - -bool SCDriver::isRecoveryValid(const EventLabel *lab) const { return isRecAcyclic(lab); } - -View SCDriver::calcPPoRfBefore(const EventLabel *lab) const -{ - auto &g = getGraph(); - View pporf; - pporf.updateIdx(lab->getPos()); - - auto *pLab = g.getPreviousLabel(lab); - if (!pLab) - return pporf; - pporf.update(pLab->getPrefixView()); - if (auto *rLab = llvm::dyn_cast(pLab)) - pporf.update(rLab->getRf()->getPrefixView()); - if (auto *tsLab = llvm::dyn_cast(pLab)) - pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); - if (auto *tjLab = llvm::dyn_cast(pLab)) - pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); - return pporf; -} -std::unique_ptr SCDriver::calculatePrefixView(const EventLabel *lab) const -{ - return std::make_unique(calcPPoRfBefore(lab)); -} - -const View &SCDriver::getHbView(const EventLabel *lab) const { return lab->view(0); } - -bool SCDriver::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(0); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector SCDriver::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto &lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(&lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool SCDriver::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(0).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(0).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator SCDriver::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator SCDriver::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(0).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(0).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator SCDriver::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector SCDriver::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInit()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector SCDriver::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - std::vector rfAfter; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - return after; -} - -std::vector SCDriver::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector SCDriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(0); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(0).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(0).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -SCDriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/SCDriver.hpp b/src/SCDriver.hpp deleted file mode 100644 index 2a30985..0000000 --- a/src/SCDriver.hpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#ifndef __SC_DRIVER_HPP__ -#define __SC_DRIVER_HPP__ - -#include "ExecutionGraph.hpp" -#include "GenMCDriver.hpp" -#include "GraphIterators.hpp" -#include "MaximalIterator.hpp" -#include "VSet.hpp" -#include "VerificationError.hpp" -#include "config.h" -#include -#include - -class SCDriver : public GenMCDriver { - -private: - enum class NodeStatus : unsigned char { unseen, entered, left }; - - struct NodeCountStatus { - NodeCountStatus() = default; - NodeCountStatus(uint16_t c, NodeStatus s) : count(c), status(s) {} - uint16_t count = 0; - NodeStatus status = NodeStatus::unseen; - }; - -public: - SCDriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); - - std::vector> calculateSaved(const EventLabel *lab); - std::vector calculateViews(const EventLabel *lab); - void updateMMViews(EventLabel *lab) override; - bool isDepTracking() const override; - bool isConsistent(const EventLabel *lab) const override; - VerificationError checkErrors(const EventLabel *lab, - const EventLabel *&race) const override; - std::vector - checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const; - bool isRecoveryValid(const EventLabel *lab) const override; - std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; - const View &getHbView(const EventLabel *lab) const override; - std::vector getCoherentStores(SAddr addr, Event read) override; - std::vector getCoherentRevisits(const WriteLabel *sLab, - const VectorClock &pporf) override; - llvm::iterator_range - getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; - -private: - bool isWriteRfBefore(Event a, Event b); - std::vector getInitRfsAtLoc(SAddr addr); - bool isHbOptRfBefore(const Event e, const Event write); - ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); - ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); - ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); - std::vector getMOOptRfAfter(const WriteLabel *sLab); - std::vector getMOInvOptRfAfter(const WriteLabel *sLab); - - void visitCalc0_0(const EventLabel *lab, View &calcRes); - void visitCalc0_1(const EventLabel *lab, View &calcRes); - void visitCalc0_2(const EventLabel *lab, View &calcRes); - - View calculate0(const EventLabel *lab); - - mutable std::vector visitedCalc0_0; - mutable std::vector visitedCalc0_1; - mutable std::vector visitedCalc0_2; - - void visitCalc1_0(const EventLabel *lab, View &calcRes); - void visitCalc1_1(const EventLabel *lab, View &calcRes); - void visitCalc1_2(const EventLabel *lab, View &calcRes); - - View calculate1(const EventLabel *lab); - - mutable std::vector visitedCalc1_0; - mutable std::vector visitedCalc1_1; - mutable std::vector visitedCalc1_2; - - bool visitInclusionLHS0_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS0_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion0(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS0_0; - mutable std::vector visitedInclusionLHS0_1; - mutable std::vector visitedInclusionRHS0_0; - mutable std::vector visitedInclusionRHS0_1; - - mutable std::vector lhsAccept0; - mutable std::vector rhsAccept0; - - mutable const EventLabel *racyLab0 = nullptr; - - void visitInclusionLHS1_0(const EventLabel *lab) const; - void visitInclusionLHS1_1(const EventLabel *lab) const; - - bool checkInclusion1(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS1_0; - mutable std::vector visitedInclusionLHS1_1; - - mutable std::vector lhsAccept1; - mutable std::vector rhsAccept1; - - mutable const EventLabel *racyLab1 = nullptr; - - bool visitInclusionLHS2_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion2(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS2_0; - mutable std::vector visitedInclusionLHS2_1; - mutable std::vector visitedInclusionLHS2_2; - mutable std::vector visitedInclusionRHS2_0; - mutable std::vector visitedInclusionRHS2_1; - - mutable std::vector lhsAccept2; - mutable std::vector rhsAccept2; - - mutable const EventLabel *racyLab2 = nullptr; - - void visitInclusionLHS3_0(const EventLabel *lab) const; - void visitInclusionLHS3_1(const EventLabel *lab) const; - void visitInclusionLHS3_2(const EventLabel *lab) const; - - bool checkInclusion3(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS3_0; - mutable std::vector visitedInclusionLHS3_1; - mutable std::vector visitedInclusionLHS3_2; - - mutable std::vector lhsAccept3; - mutable std::vector rhsAccept3; - - mutable const EventLabel *racyLab3 = nullptr; - - bool visitInclusionLHS4_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion4(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS4_0; - mutable std::vector visitedInclusionLHS4_1; - mutable std::vector visitedInclusionLHS4_2; - mutable std::vector visitedInclusionRHS4_0; - mutable std::vector visitedInclusionRHS4_1; - - mutable std::vector lhsAccept4; - mutable std::vector rhsAccept4; - - mutable const EventLabel *racyLab4 = nullptr; - - void visitInclusionLHS5_0(const EventLabel *lab) const; - void visitInclusionLHS5_1(const EventLabel *lab) const; - void visitInclusionLHS5_2(const EventLabel *lab) const; - - bool checkInclusion5(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS5_0; - mutable std::vector visitedInclusionLHS5_1; - mutable std::vector visitedInclusionLHS5_2; - - mutable std::vector lhsAccept5; - mutable std::vector rhsAccept5; - - mutable const EventLabel *racyLab5 = nullptr; - - bool visitInclusionLHS6_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS6_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion6(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS6_0; - mutable std::vector visitedInclusionLHS6_1; - mutable std::vector visitedInclusionRHS6_0; - mutable std::vector visitedInclusionRHS6_1; - - mutable std::vector lhsAccept6; - mutable std::vector rhsAccept6; - - mutable const EventLabel *racyLab6 = nullptr; - - bool visitInclusionLHS7_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS7_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion7(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS7_0; - mutable std::vector visitedInclusionLHS7_1; - mutable std::vector visitedInclusionRHS7_0; - mutable std::vector visitedInclusionRHS7_1; - - mutable std::vector lhsAccept7; - mutable std::vector rhsAccept7; - - mutable const EventLabel *racyLab7 = nullptr; - - bool visitAcyclic0_0(const EventLabel *lab) const; - - bool isAcyclic0(const EventLabel *lab) const; - - mutable std::vector visitedAcyclic0_0; - - mutable uint16_t visitedAccepting0 = 0; - bool shouldVisitAcyclic0(void) const { return true; }; - - bool isRecAcyclic(const EventLabel *lab) const; - - mutable uint16_t visitedRecAccepting = 0; - void visitPPoRf0(const EventLabel *lab, View &pporf) const; - - View calcPPoRfBefore(const EventLabel *lab) const; - - mutable std::vector visitedPPoRf0; - - mutable std::vector> saved; - mutable std::vector views; -}; - -#endif /* __SC_DRIVER_HPP__ */ diff --git a/src/SpinAssumePass.hpp b/src/SpinAssumePass.hpp deleted file mode 100644 index d4276d7..0000000 --- a/src/SpinAssumePass.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -#ifndef __SPIN_ASSUME_PASS_HPP__ -#define __SPIN_ASSUME_PASS_HPP__ - -#include "VSet.hpp" -#include -#include -#include - -class SpinAssumePass : public llvm::LoopPass { - -protected: - bool isPathToHeaderEffectFree(llvm::BasicBlock *latch, llvm::Loop *l, - bool &checkDynamically); - bool isPathToHeaderFAIZNE(llvm::BasicBlock *latch, llvm::Loop *l, - llvm::Instruction *&lastEffect); - bool isPathToHeaderLockZNE(llvm::BasicBlock *latch, llvm::Loop *l, - llvm::Instruction *&lastEffect); - -public: - static char ID; - - SpinAssumePass() : llvm::LoopPass(ID){}; - - void markSpinloopStarts(bool mark) { markStarts = mark; } - - virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const; - virtual bool runOnLoop(llvm::Loop *L, llvm::LPPassManager &LPM); - -private: - /* Whether we should mark spinloop starts */ - bool markStarts = false; -}; - -#endif /* __SPIN_ASSUME_PASS_HPP__ */ diff --git a/src/Static/LLVMModule.cpp b/src/Static/LLVMModule.cpp new file mode 100644 index 0000000..4aaf01b --- /dev/null +++ b/src/Static/LLVMModule.cpp @@ -0,0 +1,252 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#include "LLVMModule.hpp" +#include "Static/Transforms/BisimilarityCheckerPass.hpp" +#include "Static/Transforms/CallInfoCollectionPass.hpp" +#include "Static/Transforms/CodeCondenserPass.hpp" +#include "Static/Transforms/ConfirmationAnnotationPass.hpp" +#include "Static/Transforms/DeclareInternalsPass.hpp" +#include "Static/Transforms/DefineLibcFunsPass.hpp" +#include "Static/Transforms/EliminateAnnotationsPass.hpp" +#include "Static/Transforms/EliminateCASPHIsPass.hpp" +#include "Static/Transforms/EliminateCastsPass.hpp" +#include "Static/Transforms/EliminateRedundantInstPass.hpp" +#include "Static/Transforms/EliminateUnusedCodePass.hpp" +#include "Static/Transforms/EscapeCheckerPass.hpp" +#include "Static/Transforms/FunctionInlinerPass.hpp" +#include "Static/Transforms/IntrinsicLoweringPass.hpp" +#include "Static/Transforms/LoadAnnotationPass.hpp" +#include "Static/Transforms/LocalSimplifyCFGPass.hpp" +#include "Static/Transforms/LoopJumpThreadingPass.hpp" +#include "Static/Transforms/LoopUnrollPass.hpp" +#include "Static/Transforms/MDataCollectionPass.hpp" +#include "Static/Transforms/MMDetectorPass.hpp" +#include "Static/Transforms/PromoteMemIntrinsicPass.hpp" +#include "Static/Transforms/PropagateAssumesPass.hpp" +#include "Static/Transforms/SpinAssumePass.hpp" +#include "Support/Error.hpp" +#include "Support/SExprVisitor.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LLVMModule { + +auto parseLLVMModule(const std::string &filename, const std::unique_ptr &ctx) + -> std::unique_ptr +{ + llvm::SMDiagnostic err; + + auto mod = llvm::parseIRFile(filename, err, *ctx); + if (!mod) { + err.print(filename.c_str(), llvm::dbgs()); + ERROR("Could not parse LLVM IR!\n"); + } + return std::move(mod); +} + +auto cloneModule(const std::unique_ptr &mod, + const std::unique_ptr &ctx) -> std::unique_ptr +{ + /* Roundtrip the module to a stream and then back into the new context */ + std::string str; + llvm::raw_string_ostream stream(str); + + llvm::WriteBitcodeToFile(*mod, stream); + + llvm::StringRef ref(stream.str()); + std::unique_ptr buf(llvm::MemoryBuffer::getMemBuffer(ref)); + + return std::move(llvm::parseBitcodeFile(buf->getMemBufferRef(), *ctx).get()); +} + +void initializeVariableInfo(ModuleInfo &MI, PassModuleInfo &PI) +{ + for (auto &kv : PI.varInfo.globalInfo) + MI.varInfo.globalInfo[MI.idInfo.VID.at(kv.first)] = kv.second; + for (auto &kv : PI.varInfo.localInfo) { + if (MI.idInfo.VID.count(kv.first)) + MI.varInfo.localInfo[MI.idInfo.VID.at(kv.first)] = kv.second; + } + MI.varInfo.internalInfo = PI.varInfo.internalInfo; +} + +void initializeAnnotationInfo(ModuleInfo &MI, PassModuleInfo &PI) +{ + using Transformer = SExprTransformer; + Transformer tr; + + for (auto &kv : PI.annotInfo.annotMap) { + MI.annotInfo.annotMap[MI.idInfo.VID.at(kv.first)] = tr.transform( + &*kv.second, [&](llvm::Value *v) { return MI.idInfo.VID.at(v); }); + } +} + +void initializeFsInfo(ModuleInfo &MI, PassModuleInfo &PI) +{ + MI.fsInfo.filenames.insert(PI.filenames.begin(), PI.filenames.end()); +} + +void initializeModuleInfo(ModuleInfo &MI, PassModuleInfo &PI) +{ + MI.collectIDs(); + initializeVariableInfo(MI, PI); + initializeAnnotationInfo(MI, PI); + initializeFsInfo(MI, PI); + MI.determinedMM = PI.determinedMM; +} + +auto transformLLVMModule(llvm::Module &mod, ModuleInfo &MI, + const std::shared_ptr &conf) -> bool +{ + PassModuleInfo PI; + + /* NOTE: The order between the analyses, the builder and the managers matters */ + + /* First, register the analyses that we are about to use. + * We also use an (unused) pass builder to load default analyses */ + llvm::LoopAnalysisManager lam; + llvm::CGSCCAnalysisManager cgam; + llvm::FunctionAnalysisManager fam; + llvm::ModuleAnalysisManager mam; + + mam.registerPass([&] { return MDataInfo(); }); + mam.registerPass([&] { return MMAnalysis(); }); + mam.registerPass([&] { return CallAnalysis(); }); + mam.registerPass([&] { return EscapeAnalysis(); }); + fam.registerPass([&] { return BisimilarityAnalysis(); }); + fam.registerPass([&] { return LoadAnnotationAnalysis(); }); + + llvm::PassBuilder pb; + pb.registerModuleAnalyses(mam); + pb.registerCGSCCAnalyses(cgam); + pb.registerFunctionAnalyses(fam); + pb.registerLoopAnalyses(lam); + pb.crossRegisterProxies(lam, fam, cgam, mam); + + /* Then create two pass managers: a basic one and one that + runs some loop passes */ + llvm::ModulePassManager basicOptsMGR; + + basicOptsMGR.addPass(DeclareInternalsPass()); + basicOptsMGR.addPass(DefineLibcFunsPass()); + basicOptsMGR.addPass(MDataCollectionPass(PI)); + if (conf->inlineFunctions) + basicOptsMGR.addPass(FunctionInlinerPass()); + { + llvm::FunctionPassManager fpm; + /* Run after the inliner because it might generate new memcpys */ + fpm.addPass(PromoteMemIntrinsicPass()); + fpm.addPass(IntrinsicLoweringPass()); + if (conf->castElimination) + fpm.addPass(EliminateCastsPass()); + fpm.addPass(PromotePass()); + basicOptsMGR.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(fpm))); + } + basicOptsMGR.addPass(DeadArgumentEliminationPass()); + { + llvm::FunctionPassManager fpm; + fpm.addPass(LocalSimplifyCFGPass()); + fpm.addPass(EliminateAnnotationsPass()); + fpm.addPass(EliminateRedundantInstPass()); + basicOptsMGR.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(fpm))); + } + if (conf->mmDetector) + basicOptsMGR.addPass(MMDetectorPass(PI)); + + auto preserved = basicOptsMGR.run(mod, mam); + + llvm::ModulePassManager loopOptsMGR; + + { + llvm::FunctionPassManager fpm; + fpm.addPass(EliminateCASPHIsPass()); + fpm.addPass(llvm::JumpThreadingPass()); + fpm.addPass(EliminateUnusedCodePass()); + if (conf->codeCondenser && !conf->checkLiveness) + fpm.addPass(CodeCondenserPass()); + if (conf->loopJumpThreading) + fpm.addPass(createFunctionToLoopPassAdaptor(LoopJumpThreadingPass())); + loopOptsMGR.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(fpm))); + } + if (conf->spinAssume) + loopOptsMGR.addPass(SpinAssumePass(conf->checkLiveness)); + if (conf->unroll.has_value()) + loopOptsMGR.addPass( + createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( + LoopUnrollPass(*conf->unroll, conf->noUnrollFuns)))); + preserved.intersect(loopOptsMGR.run(mod, mam)); + + /* Run annotation passes last so that the module is stable */ + { + llvm::FunctionPassManager fpm; + if (conf->assumePropagation) + fpm.addPass(PropagateAssumesPass()); + if (conf->confirmAnnot) + fpm.addPass(ConfirmationAnnotationPass()); + if (conf->loadAnnot) + fpm.addPass(LoadAnnotationPass(PI.annotInfo)); + basicOptsMGR.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(fpm))); + } + + preserved.intersect(basicOptsMGR.run(mod, mam)); + + initializeModuleInfo(MI, PI); + + assert(!llvm::verifyModule(mod, &llvm::dbgs())); + return true; +} + +void printLLVMModule(llvm::Module &mod, const std::string &out) +{ + auto flags = +#if LLVM_VERSION_MAJOR < 13 + llvm::sys::fs::F_None; +#else + llvm::sys::fs::OF_None; +#endif + std::error_code errs; + auto os = std::make_unique(out.c_str(), errs, flags); + + /* TODO: Do we need an exception? If yes, properly handle it */ + if (errs) { + WARN("Failed to write transformed module to file " + out + ": " + errs.message()); + return; + } + mod.print(*os, nullptr); +} + +} // namespace LLVMModule diff --git a/src/LLVMModule.hpp b/src/Static/LLVMModule.hpp similarity index 96% rename from src/LLVMModule.hpp rename to src/Static/LLVMModule.hpp index f7aec7d..5b67f21 100644 --- a/src/LLVMModule.hpp +++ b/src/Static/LLVMModule.hpp @@ -20,8 +20,8 @@ #include "config.h" -#include "Config.hpp" -#include "ModuleInfo.hpp" +#include "Config/Config.hpp" +#include "Static/ModuleInfo.hpp" #include #include diff --git a/src/LLVMUtils.cpp b/src/Static/LLVMUtils.cpp similarity index 99% rename from src/LLVMUtils.cpp rename to src/Static/LLVMUtils.cpp index 8fe66f7..f58956d 100644 --- a/src/LLVMUtils.cpp +++ b/src/Static/LLVMUtils.cpp @@ -19,8 +19,7 @@ */ #include "LLVMUtils.hpp" -#include "CallInstWrapper.hpp" -#include "InterpreterEnumAPI.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" #include #include #include diff --git a/src/LLVMUtils.hpp b/src/Static/LLVMUtils.hpp similarity index 64% rename from src/LLVMUtils.hpp rename to src/Static/LLVMUtils.hpp index 486c161..f36de88 100644 --- a/src/LLVMUtils.hpp +++ b/src/Static/LLVMUtils.hpp @@ -18,16 +18,13 @@ * Author: Michalis Kokologiannakis */ -#ifndef __LLVM_UTILS_HPP__ -#define __LLVM_UTILS_HPP__ +#ifndef GENMC_LLVM_UTILS_HPP +#define GENMC_LLVM_UTILS_HPP -#include "Error.hpp" -#include "EventAttr.hpp" -#include "VSet.hpp" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/EventAttr.hpp" +#include "Support/Error.hpp" #include "config.h" -#ifdef LLVM_HAVE_ELIMINATE_UNCREACHABLE_BLOCKS -#include -#endif #include #include #include @@ -40,50 +37,108 @@ typedef llvm::TerminatorInst TerminatorInst; typedef llvm::Instruction TerminatorInst; #endif +#if LLVM_VERSION_MAJOR < 17 +#define GLOBALS(M) (M).getGlobalList() +#else +#define GLOBALS(M) (M).globals() +#endif + +#if LLVM_VERSION_MAJOR < 11 + +#include + +class CallInstWrapper { + +public: + /* Constructors */ + CallInstWrapper() : CS() {} + CallInstWrapper(CallSite CS) : CS(CS) {} + CallInstWrapper(CallInst *CI) : CS(CI) {} + + /* Getters emulation */ + llvm::Value *getCalledOperand() { return CS.getCalledValue(); } + llvm::Function *getCalledFunction() { return CS.getCalledFunction(); } + size_t arg_size() const { return CS.arg_size(); } + CallSite::arg_iterator arg_begin() { return CS.arg_begin(); } + CallSite::arg_iterator arg_end() { return CS.arg_end(); } + + /* Operators to use instead of member functions like + * getInstruction() that do not exist in CallBase */ + Instruction *operator&() { return CS.getInstruction(); } + +private: + CallSite CS; +}; + +#else + +class CallInstWrapper { + +public: + /* Constructors */ + CallInstWrapper() : CB(nullptr) {} + CallInstWrapper(llvm::CallBase *CB) : CB(CB) {} + CallInstWrapper(llvm::CallBase &CB) : CB(&CB) {} + CallInstWrapper(llvm::CallInst *CI) : CB(CI) {} + + /* Getters emulation */ + auto getCalledOperand() -> llvm::Value * { return CB->getCalledOperand(); } + auto getCalledFunction() -> llvm::Function * { return CB->getCalledFunction(); } + auto arg_size() const -> size_t { return CB->arg_size(); } + auto arg_begin() -> llvm::User::op_iterator { return CB->arg_begin(); } + auto arg_end() -> llvm::User::op_iterator { return CB->arg_end(); } + + auto operator&() -> llvm::Instruction * { return CB; } + +private: + llvm::CallBase *CB; +}; +#endif + /* * Returns true if o1 and o2 are the same ordering as far as a load * operation is concerned. This catches cases where e.g., * o1 is acq_rel and o2 is acq. * */ -bool areSameLoadOrdering(llvm::AtomicOrdering o1, llvm::AtomicOrdering o2); +auto areSameLoadOrdering(llvm::AtomicOrdering o1, llvm::AtomicOrdering o2) -> bool; /* * Strips all kinds of casts from val (including trunc, zext ops, etc) */ -llvm::Value *stripCasts(llvm::Value *val); +auto stripCasts(llvm::Value *val) -> llvm::Value *; /* * Strips all casts and GEPs from val */ -llvm::Value *stripCastsGEPs(llvm::Value *val); +auto stripCastsGEPs(llvm::Value *val) -> llvm::Value *; /* * Strips all casts and constant operations from val */ -llvm::Value *stripCastsConstOps(llvm::Value *val); +auto stripCastsConstOps(llvm::Value *val) -> llvm::Value *; /* * Returns the name of the function ci calls */ -std::string getCalledFunOrStripValName(const llvm::CallInst &ci); +auto getCalledFunOrStripValName(const llvm::CallInst &ci) -> std::string; /* * Returns true if its argument is an intrinsic call that does * not have any side-effects. */ -bool isIntrinsicCallNoSideEffects(const llvm::Instruction &i); +auto isIntrinsicCallNoSideEffects(const llvm::Instruction &i) -> bool; // FIXME: Change name /* * Returns true if i1 depends on o2 */ -bool isDependentOn(const llvm::Instruction *i1, const llvm::Instruction *i2); +auto isDependentOn(const llvm::Instruction *i1, const llvm::Instruction *i2) -> bool; /* * If EI extracts its value from an integer CAS instruction, returns said CAS; * otherwise returns nullptr. */ -llvm::AtomicCmpXchgInst *extractsFromCAS(llvm::ExtractValueInst *ei); +auto extractsFromCAS(llvm::ExtractValueInst *ei) -> llvm::AtomicCmpXchgInst *; /* * Returns true if its argument has side-effects. @@ -91,13 +146,14 @@ llvm::AtomicCmpXchgInst *extractsFromCAS(llvm::ExtractValueInst *ei); * Calls to non-intrinsic functions are considered to produce side-effects * unless a clean list "cleanFuns" is provided. */ -bool hasSideEffects(const llvm::Instruction *i, const VSet *cleanFuns = nullptr); +auto hasSideEffects(const llvm::Instruction *i, const VSet *cleanFuns = nullptr) + -> bool; /* * Returns true if I allocates memory. * If a list of allocFuns is provided, then these are also considered as allocating instructions. */ -bool isAlloc(const llvm::Instruction *i, const VSet *allocFuns = nullptr); +auto isAlloc(const llvm::Instruction *i, const VSet *allocFuns = nullptr) -> bool; /* * Annotates I by setting the metadata TYPE to VALUE @@ -110,7 +166,7 @@ void annotateInstruction(llvm::Instruction *i, const std::string &type, uint64_t * empty block with an unconditional jump. * Returns the destination block if it succeeded, and null otherwise. */ -llvm::BasicBlock *tryThreadSuccessor(llvm::BranchInst *term, llvm::BasicBlock *succ); +auto tryThreadSuccessor(llvm::BranchInst *term, llvm::BasicBlock *succ) -> llvm::BasicBlock *; /* * Extracts the write attribute from an (annotated) instruction. @@ -192,4 +248,4 @@ bool EliminateUnreachableBlocks(Function &F, DomTreeUpdater *DTU = nullptr, void replaceUsesWithIf(llvm::Value *Old, llvm::Value *New, llvm::function_ref ShouldReplace); -#endif /* __LLVM_UTILS_HPP__ */ +#endif /* GENMC_LLVM_UTILS_HPP */ diff --git a/src/ModuleID.hpp b/src/Static/ModuleID.hpp similarity index 92% rename from src/ModuleID.hpp rename to src/Static/ModuleID.hpp index d156242..0e2cfbc 100644 --- a/src/ModuleID.hpp +++ b/src/Static/ModuleID.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MODULE_ID_HPP__ -#define __MODULE_ID_HPP__ +#ifndef GENMC_MODULE_ID_HPP +#define GENMC_MODULE_ID_HPP #include @@ -40,4 +40,4 @@ struct ModuleID { } }; -#endif /* __MODULE_ID_HPP__ */ +#endif /* GENMC_MODULE_ID_HPP */ diff --git a/src/ModuleInfo.cpp b/src/Static/ModuleInfo.cpp similarity index 96% rename from src/ModuleInfo.cpp rename to src/Static/ModuleInfo.cpp index ca88993..83ccb27 100644 --- a/src/ModuleInfo.cpp +++ b/src/Static/ModuleInfo.cpp @@ -19,7 +19,8 @@ */ #include "ModuleInfo.hpp" -#include "SExpr.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/SExpr.hpp" #include #include @@ -36,7 +37,8 @@ void ModuleInfo::collectIDs() clear(); auto valueCount = 0u; - for (auto &gv : mod.getGlobalList()) { + + for (auto &gv : GLOBALS(mod)) { auto id = valueCount++; idInfo.VID[&gv] = id; idInfo.IDV[id] = &gv; diff --git a/src/ModuleInfo.hpp b/src/Static/ModuleInfo.hpp similarity index 92% rename from src/ModuleInfo.hpp rename to src/Static/ModuleInfo.hpp index 7144265..b399ad1 100644 --- a/src/ModuleInfo.hpp +++ b/src/Static/ModuleInfo.hpp @@ -18,20 +18,22 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MODULE_INFO_HPP__ -#define __MODULE_INFO_HPP__ - -#include "Config.hpp" -#include "ModuleID.hpp" -#include "NameInfo.hpp" -#include "SExpr.hpp" -#include "VSet.hpp" +#ifndef GENMC_MODULE_INFO_HPP +#define GENMC_MODULE_INFO_HPP + +#include "ADT/VSet.hpp" +#include "Config/Config.hpp" +#include "Static/ModuleID.hpp" +#include "Support/NameInfo.hpp" +#include "Support/SExpr.hpp" #include "config.h" #include #include #include #include +#include "ADT/value_ptr.hpp" + #include #include #include @@ -73,7 +75,7 @@ template struct VariableInfo { */ template struct AnnotationInfo { - using AnnotUM = std::unordered_map>>; + using AnnotUM = std::unordered_map, SExprCloner>>; void clear() { annotMap.clear(); } @@ -166,4 +168,4 @@ struct ModuleInfo { const llvm::Module &mod; }; -#endif /* __MODULE_INFO_HPP__ */ +#endif /* GENMC_MODULE_INFO_HPP */ diff --git a/src/BisimilarityCheckerPass.cpp b/src/Static/Transforms/BisimilarityCheckerPass.cpp similarity index 77% rename from src/BisimilarityCheckerPass.cpp rename to src/Static/Transforms/BisimilarityCheckerPass.cpp index f7e3634..1ab9d17 100644 --- a/src/BisimilarityCheckerPass.cpp +++ b/src/Static/Transforms/BisimilarityCheckerPass.cpp @@ -19,13 +19,15 @@ */ #include "BisimilarityCheckerPass.hpp" -#include "Error.hpp" +#include "Support/Error.hpp" #include #include #include +#include + using namespace llvm; -using BsPoint = BisimilarityCheckerPass::BisimilarityPoint; +using BsPoint = BisimilarityAnalysis::BisimilarityPoint; using Constraint = std::pair; /* @@ -34,25 +36,16 @@ using Constraint = std::pair; */ struct ConstrainedBsPoint { BsPoint p; - std::vector constraints; + std::vector constraints{}; - ConstrainedBsPoint(BsPoint p) : p(p), constraints() {} - ConstrainedBsPoint(BsPoint p, const std::vector &cs) : p(p), constraints(cs) {} + ConstrainedBsPoint(BsPoint p) : p(std::move(p)) {} + ConstrainedBsPoint(BsPoint p, std::vector cs) : p(p), constraints(std::move(cs)) + {} }; -void BisimilarityCheckerPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - au.setPreservesAll(); -} - -bool BisimilarityCheckerPass::doInitialization(Module &M) -{ - funcBsPoints.clear(); - return false; -} - /* Given a list of candidates, returns the ones that are satisfiables */ -std::vector getSatisfiableCandidates(const std::vector &candidates) +auto getSatisfiableCandidates(const std::vector &candidates) + -> std::vector { std::vector bsPoints; @@ -67,7 +60,7 @@ std::vector getSatisfiableCandidates(const std::vector bool { if (auto *c1 = llvm::dyn_cast(c.first)) if (auto *c2 = llvm::dyn_cast(c.second)) @@ -98,15 +91,15 @@ void filterCandidateConstraints(BsPoint &bsp, const std::vector &cs, } } } - candidates.push_back(ConstrainedBsPoint(bsp, cs)); - return; + candidates.emplace_back(bsp, cs); } -bool calcOperatorConstraints(Instruction *a, Instruction *b, std::vector &constraints) +auto calcOperatorConstraints(Instruction *a, Instruction *b, std::vector &constraints) + -> bool { std::vector cs; - for (auto i = 0u; i < a->getNumOperands(); i++) { + for (auto i = 0U; i < a->getNumOperands(); i++) { auto *opA = a->getOperand(i); auto *opB = b->getOperand(i); @@ -115,7 +108,7 @@ bool calcOperatorConstraints(Instruction *a, Instruction *b, std::vectorgetPrevNode(), b->getPrevNode(), candidates); } - return; } /* Returns the bisimilarity points of a function starting from (A, B)*/ -std::vector getBsPoints(Instruction *a, Instruction *b) +auto getBsPoints(Instruction *a, Instruction *b) -> std::vector { std::vector candidates; calcBsPointCandidates(a, b, candidates); return getSatisfiableCandidates(candidates); } -bool BisimilarityCheckerPass::runOnFunction(Function &F) +auto BisimilarityAnalysis::run(Function &F, FunctionAnalysisManager &FAM) -> Result { + funcBsPoints_.clear(); for (auto bit = F.begin(), be = F.end(); bit != be; ++bit) { /* Only handle 2 preds for the time being (assumption used below) */ if (std::distance(pred_begin(&*bit), pred_end(&*bit)) != 2) continue; - auto b1 = *pred_begin(&*bit); /* pred 1 */ - auto b2 = *(++pred_begin(&*bit)); /* pred 2 */ + auto *b1 = *pred_begin(&*bit); /* pred 1 */ + auto *b2 = *(++pred_begin(&*bit)); /* pred 2 */ /* Skip if the predecessors are the same */ if (b1 == b2) @@ -185,18 +178,18 @@ bool BisimilarityCheckerPass::runOnFunction(Function &F) sameState = false; } if (sameState) - funcBsPoints[&F].insert(funcBsPoints[&F].end(), ps.begin(), ps.end()); + funcBsPoints_.insert(funcBsPoints_.end(), ps.begin(), ps.end()); } - auto &bsps = funcBsPoints[&F]; + auto &bsps = funcBsPoints_; std::sort(bsps.begin(), bsps.end()); bsps.erase(std::unique(bsps.begin(), bsps.end()), bsps.end()); - return false; + return funcBsPoints_; } -FunctionPass *createBisimilarityCheckerPass() { return new BisimilarityCheckerPass(); } - -char BisimilarityCheckerPass::ID = 42; -static llvm::RegisterPass - P("bisimilarity-checker", "Calculates bisimilar points in all functions."); +auto BisimilarityCheckerPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses +{ + bsps_ = FAM.getResult(F); + return PreservedAnalyses::all(); +} diff --git a/src/BisimilarityCheckerPass.hpp b/src/Static/Transforms/BisimilarityCheckerPass.hpp similarity index 51% rename from src/BisimilarityCheckerPass.hpp rename to src/Static/Transforms/BisimilarityCheckerPass.hpp index e34b886..27449d8 100644 --- a/src/BisimilarityCheckerPass.hpp +++ b/src/Static/Transforms/BisimilarityCheckerPass.hpp @@ -18,37 +18,42 @@ * Author: Michalis Kokologiannakis */ -#ifndef __BISIMILARITY_CHECKER_PASS_HPP__ -#define __BISIMILARITY_CHECKER_PASS_HPP__ +#ifndef GENMC_BISIMILARITY_CHECKER_PASS_HPP +#define GENMC_BISIMILARITY_CHECKER_PASS_HPP #include -#include - -#include +#include using namespace llvm; -class BisimilarityCheckerPass : public FunctionPass { - +class BisimilarityAnalysis : public AnalysisInfoMixin { public: using BisimilarityPoint = std::pair; + using Result = std::vector; - static char ID; - - BisimilarityCheckerPass() : FunctionPass(ID) {} - virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; - virtual bool doInitialization(Module &M) override; - virtual bool runOnFunction(Function &F) override; + auto run(Function &F, FunctionAnalysisManager &FAM) -> Result; /* Returns all bisimilar points in a given function */ - const std::vector &getFuncBsPoints(Function *F) - { - return funcBsPoints[F]; - } + auto getFuncBsPoints(Function &F) -> Result { return funcBsPoints_; } + +private: + friend AnalysisInfoMixin; + static inline AnalysisKey Key; + + /* Bisimilar points for a function */ + std::vector funcBsPoints_; +}; + +class BisimilarityCheckerPass : public AnalysisInfoMixin { +public: + BisimilarityCheckerPass(std::vector &bsps) + : bsps_(bsps) + {} + + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; private: - /* Bisimilar points for all functions of the module */ - std::unordered_map> funcBsPoints; + std::vector &bsps_; }; -#endif /* __BISIMILARITY_CHECKER_PASS_HPP__ */ +#endif /* GENMC_BISIMILARITY_CHECKER_PASS_HPP */ diff --git a/src/CallInfoCollectionPass.cpp b/src/Static/Transforms/CallInfoCollectionPass.cpp similarity index 75% rename from src/CallInfoCollectionPass.cpp rename to src/Static/Transforms/CallInfoCollectionPass.cpp index e00ec82..30ec68b 100644 --- a/src/CallInfoCollectionPass.cpp +++ b/src/Static/Transforms/CallInfoCollectionPass.cpp @@ -19,9 +19,9 @@ */ #include "CallInfoCollectionPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include "config.h" #include #include @@ -33,13 +33,8 @@ using namespace llvm; -void CallInfoCollectionPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - au.setPreservesAll(); -} - -bool hasSideEffects(Function *F, SmallVector &chain, VSet &clean, - VSet &dirty) +auto hasSideEffects(Function *F, SmallVector &chain, VSet &clean, + VSet &dirty) -> bool { if (!F || dirty.count(F)) return true; @@ -70,13 +65,13 @@ bool hasSideEffects(Function *F, SmallVector &chain, VSet &clean, VSet &dirty) +auto hasSideEffects(Function *F, VSet &clean, VSet &dirty) -> bool { SmallVector chain; return hasSideEffects(F, chain, clean, dirty); } -bool isAllocating(Function *F) +auto isAllocating(Function *F) -> bool { if (!F->getReturnType()->isPointerTy()) return false; @@ -94,25 +89,25 @@ bool isAllocating(Function *F) }); } -bool CallInfoCollectionPass::runOnModule(Module &M) +auto CallAnalysis::run(Module &M, ModuleAnalysisManager &MAM) -> Result { VSet dirty; - clean.clear(); - alloc.clear(); + result_.clean.clear(); + result_.alloc.clear(); for (auto &F : M) { - if (hasSideEffects(&F, clean, dirty)) + if (hasSideEffects(&F, result_.clean, dirty)) dirty.insert(&F); else - clean.insert(&F); + result_.clean.insert(&F); if (isAllocating(&F)) - alloc.insert(&F); + result_.alloc.insert(&F); } - return false; + return result_; } -ModulePass *createCallInfoCollectionPass() { return new CallInfoCollectionPass(); } - -char CallInfoCollectionPass::ID = 42; -static llvm::RegisterPass - P("call-info-collection", "Collects information about side-effect-free functions."); +auto CallAnalysisPass::run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses +{ + AR_ = MAM.getResult(M); + return PreservedAnalyses::all(); +} diff --git a/src/Static/Transforms/CallInfoCollectionPass.hpp b/src/Static/Transforms/CallInfoCollectionPass.hpp new file mode 100644 index 0000000..4caefd9 --- /dev/null +++ b/src/Static/Transforms/CallInfoCollectionPass.hpp @@ -0,0 +1,65 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_CALL_INFO_COLLECTION_PASS_HPP +#define GENMC_CALL_INFO_COLLECTION_PASS_HPP + +#include "ADT/VSet.hpp" +#include + +namespace llvm { +class Function; +} // namespace llvm + +using namespace llvm; + +class CallAnalysis; + +struct CallAnalysisResult { + using CallSet = VSet; + + CallSet clean; + CallSet alloc; +}; + +class CallAnalysis : public AnalysisInfoMixin { +public: + using Result = CallAnalysisResult; + + auto run(Module &M, ModuleAnalysisManager &MAM) -> Result; + +private: + friend AnalysisInfoMixin; + static inline AnalysisKey Key; + + CallAnalysisResult result_; +}; + +class CallAnalysisPass : public AnalysisInfoMixin { +public: + CallAnalysisPass(CallAnalysisResult &AR) : AR_(AR) {} + + auto run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses; + +private: + CallAnalysisResult &AR_; +}; + +#endif /* GENMC_CALL_INFO_COLLECTION_PASS_HPP */ diff --git a/src/CodeCondenserPass.cpp b/src/Static/Transforms/CodeCondenserPass.cpp similarity index 76% rename from src/CodeCondenserPass.cpp rename to src/Static/Transforms/CodeCondenserPass.cpp index b5730bb..15e327f 100644 --- a/src/CodeCondenserPass.cpp +++ b/src/Static/Transforms/CodeCondenserPass.cpp @@ -20,10 +20,10 @@ #include "config.h" -#include "BisimilarityCheckerPass.hpp" #include "CodeCondenserPass.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/BisimilarityCheckerPass.hpp" +#include "Support/Error.hpp" #include #include #include @@ -33,20 +33,15 @@ #include using namespace llvm; -using BsPoint = BisimilarityCheckerPass::BisimilarityPoint; +using BsPoint = BisimilarityAnalysis::BisimilarityPoint; -void CodeCondenserPass::getAnalysisUsage(llvm::AnalysisUsage &au) const +auto CodeCondenserPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - au.addRequired(); -} - -bool CodeCondenserPass::runOnFunction(Function &F) -{ - auto &bsps = getAnalysis().getFuncBsPoints(&F); + auto bsps = FAM.getResult(F); /* Map blocks to bisimilarity points */ std::unordered_map> bbsToBsps; - for (auto &p : bsps) + for (const auto &p : bsps) bbsToBsps[p.first->getParent()].push_back(p); /* Condense the code: */ @@ -81,7 +76,7 @@ bool CodeCondenserPass::runOnFunction(Function &F) if (!term) continue; - for (auto i = 0u; i < term->getNumSuccessors(); i++) + for (auto i = 0U; i < term->getNumSuccessors(); i++) if (term->getSuccessor(i) == aNewBB) term->setSuccessor(i, bNewBB); } @@ -90,11 +85,5 @@ bool CodeCondenserPass::runOnFunction(Function &F) } /* Clear unnecessary blocks */ EliminateUnreachableBlocks(F); - return true; + return PreservedAnalyses::none(); } - -FunctionPass *createCodeCondenserPass() { return new CodeCondenserPass(); } - -char CodeCondenserPass::ID = 42; -static llvm::RegisterPass - P("code-condenser", "Reduces the size of the code by leveraging bisimilarity information."); diff --git a/src/DeclareInternalsPass.hpp b/src/Static/Transforms/CodeCondenserPass.hpp similarity index 71% rename from src/DeclareInternalsPass.hpp rename to src/Static/Transforms/CodeCondenserPass.hpp index 1f2a942..4103661 100644 --- a/src/DeclareInternalsPass.hpp +++ b/src/Static/Transforms/CodeCondenserPass.hpp @@ -18,17 +18,16 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DECLARE_INTERNALS_PASS_HPP__ -#define __DECLARE_INTERNALS_PASS_HPP__ +#ifndef GENMC_CODE_CONDENSER_PASS_HPP +#define GENMC_CODE_CONDENSER_PASS_HPP -#include +#include -class DeclareInternalsPass : public llvm::ModulePass { -public: - static char ID; +using namespace llvm; - DeclareInternalsPass() : ModulePass(ID){}; - virtual bool runOnModule(llvm::Module &M); +class CodeCondenserPass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; }; -#endif /* __DECLARE_INTERNALS_PASS_HPP__ */ +#endif /* GENMC_CODE_CONDENSER_PASS_HPP */ diff --git a/src/ConfirmationAnnotationPass.cpp b/src/Static/Transforms/ConfirmationAnnotationPass.cpp similarity index 80% rename from src/ConfirmationAnnotationPass.cpp rename to src/Static/Transforms/ConfirmationAnnotationPass.cpp index af23961..47ec5ea 100644 --- a/src/ConfirmationAnnotationPass.cpp +++ b/src/Static/Transforms/ConfirmationAnnotationPass.cpp @@ -19,10 +19,10 @@ */ #include "ConfirmationAnnotationPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" -#include "config.h" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" + #include #include #include @@ -31,22 +31,14 @@ using namespace llvm; -void ConfirmationAnnotationPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - au.addRequired(); - au.addRequired(); - au.setPreservesAll(); -} - -bool isSpinEndCall(Instruction *i) +auto isSpinEndCall(Instruction *i) -> bool { auto *ci = llvm::dyn_cast(i); if (!ci) return false; auto name = getCalledFunOrStripValName(*ci); - return isInternalFunction(name) && - internalFunNames.at(name) == InternalFunctions::FN_SpinEnd; + return isSpinEndFunction(name); } /* @@ -54,7 +46,7 @@ bool isSpinEndCall(Instruction *i) * returns a candidate confirmation instruction: either a CAS or a CMP * between two loads. */ -Instruction *getConfirmationCandidate(Instruction *i) +auto getConfirmationCandidate(Instruction *i) -> Instruction * { auto *si = stripCastsConstOps(i); if (auto *ei = dyn_cast(si)) @@ -77,7 +69,7 @@ Instruction *getConfirmationCandidate(Instruction *i) * returns the common candidate confirmation instruction among * the block's predecessors. */ -Instruction *getCommonConfirmationFromPreds(BasicBlock *bb) +auto getCommonConfirmationFromPreds(BasicBlock *bb) -> Instruction * { Instruction *conf = nullptr; if (std::all_of(pred_begin(bb), pred_end(bb), [&conf](const BasicBlock *pred) { @@ -102,20 +94,21 @@ Instruction *getCommonConfirmationFromPreds(BasicBlock *bb) * (e.g., by checking that the loads read from the same place). * This should be done separately later. */ -Instruction *spinEndsOnConfirmation(CallInst *ci) +auto spinEndsOnConfirmation(CallInst *ci) -> Instruction * { auto *endValue = ci->getArgOperand(0); if (auto *i = dyn_cast(endValue)) { return getConfirmationCandidate(i); - } else if (auto *c = dyn_cast(endValue)) { + } + if (auto *c = dyn_cast(endValue)) { if (c->getType()->isIntegerTy() && c->isZeroValue()) return getCommonConfirmationFromPreds(ci->getParent()); } return nullptr; } -std::pair getConfirmationPair(Instruction *i, LoopInfo &LI, - DominatorTree &DT) +auto getConfirmationPair(Instruction *i, LoopInfo &LI, DominatorTree &DT) + -> std::pair { LoadInst *spec = nullptr; Instruction *conf = nullptr; @@ -184,15 +177,8 @@ void annotate(Function &F, LoopInfo &LI, DominatorTree &DT) } } -bool ConfirmationAnnotationPass::runOnFunction(llvm::Function &F) +auto ConfirmationAnnotationPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - annotate(F, getAnalysis().getLoopInfo(), - getAnalysis().getDomTree()); - return false; + annotate(F, FAM.getResult(F), FAM.getResult(F)); + return PreservedAnalyses::all(); } - -FunctionPass *createConfirmationAnnotationPass() { return new ConfirmationAnnotationPass(); } - -char ConfirmationAnnotationPass::ID = 42; -static llvm::RegisterPass - P("annotate-confirmation", "Annotates loads used in confirmation patterns."); diff --git a/src/CodeCondenserPass.hpp b/src/Static/Transforms/ConfirmationAnnotationPass.hpp similarity index 67% rename from src/CodeCondenserPass.hpp rename to src/Static/Transforms/ConfirmationAnnotationPass.hpp index c8846fd..65fd934 100644 --- a/src/CodeCondenserPass.hpp +++ b/src/Static/Transforms/ConfirmationAnnotationPass.hpp @@ -18,22 +18,16 @@ * Author: Michalis Kokologiannakis */ -#ifndef __CODE_CONDENSER_PASS_HPP__ -#define __CODE_CONDENSER_PASS_HPP__ +#ifndef GENMC_CONFIRMATION_ANNOTATION_PASS_HPP +#define GENMC_CONFIRMATION_ANNOTATION_PASS_HPP -#include -#include +#include using namespace llvm; -class CodeCondenserPass : public FunctionPass { - +class ConfirmationAnnotationPass : public PassInfoMixin { public: - static char ID; - - CodeCondenserPass() : FunctionPass(ID) {} - virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &F) override; + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; }; -#endif /* __CODE_CONDENSER_PASS_HPP__ */ +#endif /* GENMC_CONFIRMATION_ANNOTATION_PASS_HPP */ diff --git a/src/DeclareInternalsPass.cpp b/src/Static/Transforms/DeclareInternalsPass.cpp similarity index 65% rename from src/DeclareInternalsPass.cpp rename to src/Static/Transforms/DeclareInternalsPass.cpp index 2a7c3b6..a0abe48 100644 --- a/src/DeclareInternalsPass.cpp +++ b/src/Static/Transforms/DeclareInternalsPass.cpp @@ -19,36 +19,40 @@ */ #include "DeclareInternalsPass.hpp" -#include "Error.hpp" -#include +#include "Support/Error.hpp" + +#include #include #include #include #include #include +#include +#include +#include using namespace llvm; -bool declareInternal(Module &M, const std::string &name, Type *retTyp, - const ArrayRef &argTyps) +auto declareInternal(Module &M, const std::string &name, Type *retTyp, + const ArrayRef &argTyps) -> bool { auto *fun = M.getFunction(name); if (fun) return false; - auto funTyp = FunctionType::get(retTyp, argTyps, false); + auto *funTyp = FunctionType::get(retTyp, argTyps, false); auto funAttrs = AttributeList::get(M.getContext(), AttributeList::FunctionIndex, std::vector({Attribute::NoUnwind})); M.getOrInsertFunction(name, funTyp, funAttrs); return true; } -bool DeclareInternalsPass::runOnModule(Module &M) +PreservedAnalyses DeclareInternalsPass::run(Module &M, ModuleAnalysisManager &AM) { bool modified = false; modified |= declareInternal(M, "__VERIFIER_assume", Type::getVoidTy(M.getContext()), - {Type::getInt32Ty(M.getContext())}); + {Type::getInt1Ty(M.getContext())}); modified |= declareInternal(M, "__VERIFIER_kill_thread", Type::getVoidTy(M.getContext()), {Type::getInt1Ty(M.getContext())}); modified |= declareInternal(M, "__VERIFIER_opt_begin", Type::getInt1Ty(M.getContext()), {}); @@ -62,11 +66,24 @@ bool DeclareInternalsPass::runOnModule(Module &M) Type::getVoidTy(M.getContext()), {}); modified |= declareInternal(M, "__VERIFIER_lockZNE_spin_end", Type::getVoidTy(M.getContext()), {}); - return modified; + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } -ModulePass *createDeclareInternalsPass() { return new DeclareInternalsPass(); } - -char DeclareInternalsPass::ID = 42; -static llvm::RegisterPass P("declare-internals", - "Declares internal functions."); +//----------------------------------------------------------------------------- +// New PM Registration +//----------------------------------------------------------------------------- +auto getDeclareInternalsPluginInfo() -> PassPluginLibraryInfo +{ + return {LLVM_PLUGIN_API_VERSION, "DeclareInternals", LLVM_VERSION_STRING, + [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &MPM, + ArrayRef) { + if (Name == "declare-internals") { + MPM.addPass(DeclareInternalsPass()); + return true; + } + return false; + }); + }}; +} diff --git a/src/Static/Transforms/DeclareInternalsPass.hpp b/src/Static/Transforms/DeclareInternalsPass.hpp new file mode 100644 index 0000000..bfc2791 --- /dev/null +++ b/src/Static/Transforms/DeclareInternalsPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_DECLARE_INTERNALS_PASS_HPP +#define GENMC_DECLARE_INTERNALS_PASS_HPP + +#include + +using namespace llvm; + +class DeclareInternalsPass : public PassInfoMixin { +public: + auto run(Module &M, ModuleAnalysisManager &AM) -> PreservedAnalyses; +}; + +#endif /* GENMC_DECLARE_INTERNALS_PASS_HPP */ diff --git a/src/DefineLibcFunsPass.cpp b/src/Static/Transforms/DefineLibcFunsPass.cpp similarity index 51% rename from src/DefineLibcFunsPass.cpp rename to src/Static/Transforms/DefineLibcFunsPass.cpp index a3f9741..b2ae2c2 100644 --- a/src/DefineLibcFunsPass.cpp +++ b/src/Static/Transforms/DefineLibcFunsPass.cpp @@ -19,46 +19,59 @@ */ #include "DefineLibcFunsPass.hpp" -#include "Error.hpp" +#include "Support/Error.hpp" #include #include #include +#include -void DefineLibcFunsPass::getAnalysisUsage(llvm::AnalysisUsage &AU) const {} +using namespace llvm; -void DefineLibcFunsPass::replaceFunWithNop(llvm::Module &M, std::string name) +void replaceFunWithNop(Module &M, std::string name) { - llvm::Function *F = M.getFunction(name); + auto *F = M.getFunction(name); if (!F || !F->isDeclaration()) return; - llvm::Value *res = 0; - llvm::Type *retTy = F->getReturnType(); + Value *res = nullptr; + Type *retTy = F->getReturnType(); if (retTy->isIntegerTy()) - res = llvm::ConstantInt::get(retTy, 0); + res = ConstantInt::get(retTy, 0); else if (retTy->isVoidTy()) - res = 0; + res = nullptr; else if (retTy->isPointerTy()) - res = llvm::ConstantPointerNull::get(static_cast(retTy)); + res = ConstantPointerNull::get(dyn_cast(retTy)); else WARN("Could not add definition for " + name + "!\n"); - llvm::BasicBlock *BB = llvm::BasicBlock::Create(F->getContext(), "", F); - llvm::ReturnInst::Create(F->getContext(), res, BB); - return; + auto *BB = BasicBlock::Create(F->getContext(), "", F); + ReturnInst::Create(F->getContext(), res, BB); } -bool DefineLibcFunsPass::runOnModule(llvm::Module &M) +auto DefineLibcFunsPass::run(Module &M, ModuleAnalysisManager &AM) -> PreservedAnalyses { replaceFunWithNop(M, "fclose"); replaceFunWithNop(M, "fopen"); replaceFunWithNop(M, "fflush"); replaceFunWithNop(M, "fprintf"); - return true; + return PreservedAnalyses::all(); } -llvm::ModulePass *createDefineLibcFunsPass() { return new DefineLibcFunsPass(); } - -char DefineLibcFunsPass::ID = 42; -static llvm::RegisterPass X("define-libc", - "Define some standard libc functions."); +//----------------------------------------------------------------------------- +// New PM Registration +//----------------------------------------------------------------------------- +auto getDefineLibcFunsPluginInfo() -> PassPluginLibraryInfo +{ + return {LLVM_PLUGIN_API_VERSION, "DefineLibcFuns", LLVM_VERSION_STRING, + [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &MPM, + ArrayRef) { + if (Name == "define-libc-funs") { + MPM.addPass(DefineLibcFunsPass()); + return true; + } + return false; + }); + }}; +} diff --git a/src/Static/Transforms/DefineLibcFunsPass.hpp b/src/Static/Transforms/DefineLibcFunsPass.hpp new file mode 100644 index 0000000..cf5c7b9 --- /dev/null +++ b/src/Static/Transforms/DefineLibcFunsPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_DEFINE_LIBC_FUNS_PASS_HPP +#define GENMC_DEFINE_LIBC_FUNS_PASS_HPP + +#include + +using namespace llvm; + +class DefineLibcFunsPass : public PassInfoMixin { +public: + auto run(Module &M, ModuleAnalysisManager &AM) -> PreservedAnalyses; +}; + +#endif /* GENMC_DEFINE_LIBC_FUNS_PASS_HPP */ diff --git a/src/EliminateAnnotationsPass.cpp b/src/Static/Transforms/EliminateAnnotationsPass.cpp similarity index 73% rename from src/EliminateAnnotationsPass.cpp rename to src/Static/Transforms/EliminateAnnotationsPass.cpp index 2df5426..0130171 100644 --- a/src/EliminateAnnotationsPass.cpp +++ b/src/Static/Transforms/EliminateAnnotationsPass.cpp @@ -19,9 +19,9 @@ */ #include "EliminateAnnotationsPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include "config.h" #include @@ -37,14 +37,7 @@ using namespace llvm; #define POSTDOM_PASS PostDominatorTreeWrapperPass #define GET_POSTDOM_PASS() getAnalysis().getPostDomTree(); -void EliminateAnnotationsPass::getAnalysisUsage(AnalysisUsage &AU) const -{ - AU.addRequired(); - AU.addRequired(); - AU.setPreservesAll(); -} - -bool isAnnotationBegin(Instruction *i) +auto isAnnotationBegin(Instruction *i) -> bool { auto *ci = llvm::dyn_cast(i); if (!ci) @@ -52,10 +45,10 @@ bool isAnnotationBegin(Instruction *i) auto name = getCalledFunOrStripValName(*ci); return isInternalFunction(name) && - internalFunNames.at(name) == InternalFunctions::FN_AnnotateBegin; + internalFunNames.at(name) == InternalFunctions::AnnotateBegin; } -bool isAnnotationEnd(Instruction *i) +auto isAnnotationEnd(Instruction *i) -> bool { auto *ci = llvm::dyn_cast(i); if (!ci) @@ -63,17 +56,17 @@ bool isAnnotationEnd(Instruction *i) auto name = getCalledFunOrStripValName(*ci); return isInternalFunction(name) && - internalFunNames.at(name) == InternalFunctions::FN_AnnotateEnd; + internalFunNames.at(name) == InternalFunctions::AnnotateEnd; } -uint64_t getAnnotationValue(CallInst *ci) +auto getAnnotationValue(CallInst *ci) -> uint64_t { auto *funArg = llvm::dyn_cast(ci->getOperand(0)); BUG_ON(!funArg); return funArg->getValue().getLimitedValue(); } -bool annotateInstructions(CallInst *begin, CallInst *end) +auto annotateInstructions(CallInst *begin, CallInst *end) -> bool { if (!begin || !end) return false; @@ -105,8 +98,8 @@ bool annotateInstructions(CallInst *begin, CallInst *end) return true; } -CallInst *findMatchingEnd(CallInst *begin, const std::vector &ends, DominatorTree &DT, - PostDominatorTree &PDT) +auto findMatchingEnd(CallInst *begin, const std::vector &ends, DominatorTree &DT, + PostDominatorTree &PDT) -> CallInst * { auto it = std::find_if(ends.begin(), ends.end(), [&](auto *ei) { return getAnnotationValue(begin) == getAnnotationValue(ei) && @@ -122,43 +115,33 @@ CallInst *findMatchingEnd(CallInst *begin, const std::vector &ends, return *it; } -bool EliminateAnnotationsPass::runOnFunction(Function &F) +auto EliminateAnnotationsPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - std::vector begins, ends; + std::vector begins; + std::vector ends; - std::for_each(inst_begin(F), inst_end(F), [&](auto &i) { + for (auto &i : instructions(F)) { if (isAnnotationBegin(&i)) begins.push_back(dyn_cast(&i)); else if (isAnnotationEnd(&i)) ends.push_back(dyn_cast(&i)); - }); + } - auto &DT = getAnalysis().getDomTree(); - auto &PDT = GET_POSTDOM_PASS(); + auto &DT = FAM.getResult(F); + auto &PDT = FAM.getResult(F); VSet toDelete; auto changed = false; - std::for_each(begins.begin(), begins.end(), [&](auto *bi) { + for (auto *bi : begins) { auto *ei = findMatchingEnd(bi, ends, DT, PDT); BUG_ON(!ei); changed |= annotateInstructions(bi, ei); toDelete.insert(bi); toDelete.insert(ei); - }); - + } for (auto *i : toDelete) { i->eraseFromParent(); changed = true; } - return changed; -} - -Pass *createEliminateAnnotationsPass() -{ - auto *p = new EliminateAnnotationsPass(); - return p; + return changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char EliminateAnnotationsPass::ID = 42; -static llvm::RegisterPass P("elim-annots", - "Eliminates intrinsic annotations."); diff --git a/src/Static/Transforms/EliminateAnnotationsPass.hpp b/src/Static/Transforms/EliminateAnnotationsPass.hpp new file mode 100644 index 0000000..b7361f4 --- /dev/null +++ b/src/Static/Transforms/EliminateAnnotationsPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_ELIMINATE_ANNOTATIONS_PASS_HPP +#define GENMC_ELIMINATE_ANNOTATIONS_PASS_HPP + +#include + +using namespace llvm; + +class EliminateAnnotationsPass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_ELIMINATE_ANNOTATIONS_PASS_HPP */ diff --git a/src/EliminateCASPHIsPass.cpp b/src/Static/Transforms/EliminateCASPHIsPass.cpp similarity index 84% rename from src/EliminateCASPHIsPass.cpp rename to src/Static/Transforms/EliminateCASPHIsPass.cpp index bacb31f..5bd0d23 100644 --- a/src/EliminateCASPHIsPass.cpp +++ b/src/Static/Transforms/EliminateCASPHIsPass.cpp @@ -19,9 +19,9 @@ */ #include "EliminateCASPHIsPass.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" -#include "VSet.hpp" +#include "ADT/VSet.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include "config.h" #include @@ -34,12 +34,7 @@ using namespace llvm; -void EliminateCASPHIsPass::getAnalysisUsage(AnalysisUsage &AU) const -{ - AU.addRequired(); -} - -ExtractValueInst *hasPHIIncomingExtract(llvm::PHINode *phi) +auto hasPHIIncomingExtract(llvm::PHINode *phi) -> ExtractValueInst * { for (Value *val : phi->incoming_values()) if (auto *ei = dyn_cast(val)) @@ -53,7 +48,8 @@ ExtractValueInst *hasPHIIncomingExtract(llvm::PHINode *phi) * Populates TODELETE with the instructions that need to be erased. * May leave the CFG in an invalid state, requiring cleanup. */ -bool tryEliminateCASPHI(llvm::PHINode *phi, DominatorTree &DT, std::vector &toDelete) +auto tryEliminateCASPHI(llvm::PHINode *phi, DominatorTree &DT, std::vector &toDelete) + -> bool { /* The PHI must have exactly two incomings... */ if (phi->getNumIncomingValues() != 2) @@ -112,12 +108,12 @@ bool tryEliminateCASPHI(llvm::PHINode *phi, DominatorTree &DT, std::vector PreservedAnalyses { std::vector toDelete; auto modified = false; - auto &DT = getAnalysis().getDomTree(); + auto &DT = FAM.getResult(F); for (auto &BB : F) { for (auto it = BB.begin(); auto phi = llvm::dyn_cast(it); ++it) modified |= tryEliminateCASPHI(phi, DT, toDelete); @@ -126,15 +122,5 @@ bool EliminateCASPHIsPass::runOnFunction(Function &F) EliminateUnreachableBlocks(F); std::for_each(toDelete.begin(), toDelete.end(), [](Instruction *i) { i->eraseFromParent(); }); - return modified; + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -Pass *createEliminateCASPHIsPass() -{ - auto *p = new EliminateCASPHIsPass(); - return p; -} - -char EliminateCASPHIsPass::ID = 42; -static llvm::RegisterPass P("elim-cas-phis", - "Eliminates certain CAS-related PHIs."); diff --git a/src/Static/Transforms/EliminateCASPHIsPass.hpp b/src/Static/Transforms/EliminateCASPHIsPass.hpp new file mode 100644 index 0000000..6057664 --- /dev/null +++ b/src/Static/Transforms/EliminateCASPHIsPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_ELIMINATE_CAS_PHIS_PASS_HPP +#define GENMC_ELIMINATE_CAS_PHIS_PASS_HPP + +#include + +using namespace llvm; + +class EliminateCASPHIsPass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_ELIMINATE_CAS_PHIS_PASS_HPP */ diff --git a/src/EliminateCastsPass.cpp b/src/Static/Transforms/EliminateCastsPass.cpp similarity index 86% rename from src/EliminateCastsPass.cpp rename to src/Static/Transforms/EliminateCastsPass.cpp index 858cef2..478088c 100644 --- a/src/EliminateCastsPass.cpp +++ b/src/Static/Transforms/EliminateCastsPass.cpp @@ -19,12 +19,11 @@ */ #include "EliminateCastsPass.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" -#include "VSet.hpp" +#include "ADT/VSet.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include "config.h" -#include #include #include #include @@ -36,9 +35,6 @@ #include #include #include -#if defined(HAVE_LLVM_TRANSFORMS_UTILS_H) -#include -#endif #include using namespace llvm; @@ -71,30 +67,23 @@ using namespace llvm; #define GET_INST_SYNC_SCOPE(i) i->getSyncScopeID() -void EliminateCastsPass::getAnalysisUsage(AnalysisUsage &AU) const -{ - AU.addRequired(); - AU.addRequired(); - AU.setPreservesCFG(); -} - /* Opaque pointers should render this pass obsolete */ #if LLVM_VERSION_MAJOR <= 14 -static bool haveSameSizePointees(const Type *p1, const Type *p2, const DataLayout &DL) +static auto haveSameSizePointees(const Type *p1, const Type *p2, const DataLayout &DL) -> bool { - auto *pTy1 = dyn_cast(p1); - auto *pTy2 = dyn_cast(p2); + const auto *pTy1 = dyn_cast(p1); + const auto *pTy2 = dyn_cast(p2); return pTy1 && pTy2 && DL.getTypeAllocSize(pTy1->getElementType()) == DL.getTypeAllocSize(pTy2->getElementType()); } -static bool isUnpromotablePureHelper(User *u, std::vector &aliases); +static auto isUnpromotablePureHelper(User *u, std::vector &aliases) -> bool; /* Return whether u is pure; if it is, it will be returned in ALIASES with its aliases */ -static bool isUserPure(User *u, std::vector &aliases) +static auto isUserPure(User *u, std::vector &aliases) -> bool { /* We only allow direct, non-volatile loads and stores, as well as "pure" * bitcasts (only used by direct, non-volatile loads and stores). @@ -102,12 +91,15 @@ static bool isUserPure(User *u, std::vector &aliases) * allocas.) */ if (auto *li = dyn_cast(u)) { return !li->isVolatile(); - } else if (auto *si = dyn_cast(u)) { + } + if (auto *si = dyn_cast(u)) { /* Don't allow a store OF the U, only INTO the U */ return !si->isVolatile() && si->getOperand(0) != aliases.back(); - } else if (auto *ii = dyn_cast(u)) { + } + if (auto *ii = dyn_cast(u)) { return IS_LIFETIME_START_OR_END(ii) || IS_DROPPABLE(ii); - } else if (auto *bci = dyn_cast(u)) { + } + if (auto *bci = dyn_cast(u)) { if (ONLY_USED_BY_MARKERS_OR_DROPPABLE(bci)) return true; if (!haveSameSizePointees(bci->getSrcTy(), bci->getDestTy(), @@ -115,22 +107,24 @@ static bool isUserPure(User *u, std::vector &aliases) return false; aliases.push_back(bci); return isUnpromotablePureHelper(bci, aliases); - } else if (auto *gepi = dyn_cast(u)) { + } + if (auto *gepi = dyn_cast(u)) { return gepi->hasAllZeroIndices() && ONLY_USED_BY_MARKERS_OR_DROPPABLE(gepi); - } else if (auto *asci = dyn_cast(u)) { + } + if (auto *asci = dyn_cast(u)) { return onlyUsedByLifetimeMarkers(asci); } /* All other cases are not safe*/ return false; } -static bool isUnpromotablePureHelper(User *i, std::vector &aliases) +static auto isUnpromotablePureHelper(User *i, std::vector &aliases) -> bool { return std::all_of(i->users().begin(), i->users().end(), [&aliases](User *u) { return isUserPure(u, aliases); }); } -static bool isUnpromotablePure(Instruction *i, std::vector &aliases) +static auto isUnpromotablePure(Instruction *i, std::vector &aliases) -> bool { aliases.push_back(i); auto pure = isUnpromotablePureHelper(i, aliases); @@ -139,8 +133,8 @@ static bool isUnpromotablePure(Instruction *i, std::vector &alias return pure; } -static Instruction::CastOps isEliminableCastPair(const CastInst *CI1, const CastInst *CI2, - const DataLayout &DL) +static auto isEliminableCastPair(const CastInst *CI1, const CastInst *CI2, const DataLayout &DL) + -> Instruction::CastOps { Type *SrcTy = CI1->getSrcTy(); Type *MidTy = CI1->getDestTy(); @@ -163,7 +157,7 @@ static Instruction::CastOps isEliminableCastPair(const CastInst *CI1, const Cast return Instruction::CastOps(Res); } -static Value *isLoadCastedFromSameSrcType(const LoadInst *li, CastInst &ci) +static auto isLoadCastedFromSameSrcType(const LoadInst *li, CastInst &ci) -> Value * { auto *M = li->getModule(); auto &DL = M->getDataLayout(); @@ -202,7 +196,7 @@ static void replaceAndMarkDelete(Instruction *toDel, Value *toRepl, deleted->insert(toDel); } -static Instruction *castToType(Value *a, Type *typ, Instruction *insertBefore) +static auto castToType(Value *a, Type *typ, Instruction *insertBefore) -> Instruction * { if (a->getType()->isPointerTy() && typ->isPointerTy()) return new BitCastInst(a, typ, "", insertBefore); @@ -249,7 +243,6 @@ static void transformStoredBitcast(CastInst &ci, StoreInst *si, VSetisVolatile(), GET_INST_ALIGN(si), si->getOrdering(), GET_INST_SYNC_SCOPE(si), si); replaceAndMarkDelete(si, store); - return; } static void transformLoadedBitcast(CastInst &ci, LoadInst *li, VSet &deleted) @@ -261,14 +254,13 @@ static void transformLoadedBitcast(CastInst &ci, LoadInst *li, VSetgetType(), li); replaceAndMarkDelete(li, cast, &deleted); - return; } /* Performs some common transformations on the cast and deletes it, if necessary. * Returns true if the transformation succeeded (and the caller should delete CI), * and sets TRANSFORMED to its replacement. */ -static bool commonCastTransforms(CastInst &ci, std::vector &aliases, - VSet &deleted) +static auto commonCastTransforms(CastInst &ci, std::vector &aliases, + VSet &deleted) -> bool { const DataLayout &DL = ci.getModule()->getDataLayout(); Value *src = ci.getOperand(0); @@ -325,7 +317,7 @@ static bool commonCastTransforms(CastInst &ci, std::vector &alias return false; } -static bool eliminateAllocaCasts(std::vector &aliases) +static auto eliminateAllocaCasts(std::vector &aliases) -> bool { if (aliases.empty()) return false; @@ -357,7 +349,7 @@ static bool eliminateAllocaCasts(std::vector &aliases) return eliminated; } -static bool eliminateCasts(Function &F, DominatorTree &DT, AssumptionCache &AC) +static auto eliminateCasts(Function &F, DominatorTree &DT) -> bool { auto &eBB = F.getEntryBlock(); bool changed = true; @@ -441,7 +433,7 @@ static bool introduceAllocaCasts(AllocaInst *ai) return false; } -static bool introduceCasts(Function &F, DominatorTree &DT, AssumptionCache &AC) +static bool introduceCasts(Function &F, DominatorTree &DT) { auto &eBB = F.getEntryBlock(); auto modified = false; @@ -464,22 +456,13 @@ static bool introduceCasts(Function &F, DominatorTree &DT, AssumptionCache &AC) } #endif /* LLVM_VERSION_MAJOR <= 14 */ -bool EliminateCastsPass::runOnFunction(Function &F) +auto EliminateCastsPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - auto &DT = getAnalysis().getDomTree(); - auto &AC = getAnalysis().getAssumptionCache(F); + auto &DT = FAM.getResult(F); #if LLVM_VERSION_MAJOR <= 14 - return eliminateCasts(F, DT, AC); + auto modified = eliminateCasts(F, DT); #else - return introduceCasts(F, DT, AC); + auto modified = introduceCasts(F, DT); #endif + return modified ? PreservedAnalyses::none() : PreservedAnalyses::none(); } - -Pass *createEliminateCastsPass() -{ - auto *p = new EliminateCastsPass(); - return p; -} - -char EliminateCastsPass::ID = 42; -static llvm::RegisterPass P("elim-casts", "Eliminates certain forms of casts."); diff --git a/src/EliminateCastsPass.hpp b/src/Static/Transforms/EliminateCastsPass.hpp similarity index 68% rename from src/EliminateCastsPass.hpp rename to src/Static/Transforms/EliminateCastsPass.hpp index 4cec7ab..d28c353 100644 --- a/src/EliminateCastsPass.hpp +++ b/src/Static/Transforms/EliminateCastsPass.hpp @@ -18,21 +18,16 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ELIMINATE_CASTS_PASS_HPP__ -#define __ELIMINATE_CASTS_PASS_HPP__ +#ifndef GENMC_ELIMINATE_CASTS_PASS_HPP +#define GENMC_ELIMINATE_CASTS_PASS_HPP -#include +#include -class EliminateCastsPass : public llvm::FunctionPass { +using namespace llvm; +class EliminateCastsPass : public PassInfoMixin { public: - static char ID; - - EliminateCastsPass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; }; -#endif /* __ELIMINATE_CASTS_PASS_HPP__ */ +#endif /* GENMC_ELIMINATE_CASTS_PASS_HPP */ diff --git a/src/EliminateRedundantInstPass.cpp b/src/Static/Transforms/EliminateRedundantInstPass.cpp similarity index 74% rename from src/EliminateRedundantInstPass.cpp rename to src/Static/Transforms/EliminateRedundantInstPass.cpp index 3d47b41..fc41d21 100644 --- a/src/EliminateRedundantInstPass.cpp +++ b/src/Static/Transforms/EliminateRedundantInstPass.cpp @@ -19,8 +19,8 @@ */ #include "EliminateRedundantInstPass.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include "config.h" #include @@ -31,15 +31,14 @@ using namespace llvm; -void EliminateRedundantInstPass::getAnalysisUsage(AnalysisUsage &au) const {} - -static bool isRedundantCastPair(const CastInst *ci1, const CastInst *ci2, const DataLayout &DL) +static auto isRedundantCastPair(const CastInst *ci1, const CastInst *ci2, const DataLayout &DL) + -> bool { return ci1->getSrcTy() == ci2->getDestTy() && DL.getTypeAllocSize(ci1->getDestTy()) >= DL.getTypeAllocSize(ci1->getSrcTy()); } -static bool eliminateRedundantInst(Function &F) +static auto eliminateRedundantInst(Function &F) -> bool { const DataLayout &DL = F.getParent()->getDataLayout(); auto modified = false; @@ -64,14 +63,7 @@ static bool eliminateRedundantInst(Function &F) return modified; } -bool EliminateRedundantInstPass::runOnFunction(Function &F) { return eliminateRedundantInst(F); } - -Pass *createEliminateRedundantInstPass() +auto EliminateRedundantInstPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - auto *p = new EliminateRedundantInstPass(); - return p; + return eliminateRedundantInst(F) ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char EliminateRedundantInstPass::ID = 42; -static llvm::RegisterPass P("eliminate-redundant-inst", - "Removes some redundant instructions."); diff --git a/src/Static/Transforms/EliminateRedundantInstPass.hpp b/src/Static/Transforms/EliminateRedundantInstPass.hpp new file mode 100644 index 0000000..ab5a608 --- /dev/null +++ b/src/Static/Transforms/EliminateRedundantInstPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_ELIMINATE_REDUNDANT_INST_PASS_HPP +#define GENMC_ELIMINATE_REDUNDANT_INST_PASS_HPP + +#include + +using namespace llvm; + +class EliminateRedundantInstPass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_ELIMINATE_REDUNDANT_INST_PASS_HPP */ diff --git a/src/EliminateUnusedCodePass.cpp b/src/Static/Transforms/EliminateUnusedCodePass.cpp similarity index 77% rename from src/EliminateUnusedCodePass.cpp rename to src/Static/Transforms/EliminateUnusedCodePass.cpp index 431a790..79b1168 100644 --- a/src/EliminateUnusedCodePass.cpp +++ b/src/Static/Transforms/EliminateUnusedCodePass.cpp @@ -19,7 +19,7 @@ */ #include "EliminateUnusedCodePass.hpp" -#include "Error.hpp" +#include "Support/Error.hpp" #include "config.h" #include @@ -38,11 +38,12 @@ using namespace llvm; -void EliminateUnusedCodePass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); } - -bool isEliminable(Instruction *i) { return !MAY_BE_MEM_DEPENDENT(*i) && !i->isTerminator(); } +auto isEliminable(Instruction *i) -> bool +{ + return !MAY_BE_MEM_DEPENDENT(*i) && !i->isTerminator(); +} -static bool eliminateUnusedCode(Function &F) +static auto eliminateUnusedCode(Function &F) -> bool { SmallPtrSet alive; SmallSetVector worklist; @@ -78,13 +79,7 @@ static bool eliminateUnusedCode(Function &F) return !worklist.empty(); } -bool EliminateUnusedCodePass::runOnFunction(Function &F) { return eliminateUnusedCode(F); } - -Pass *createEliminateUnusedCodePass() +auto EliminateUnusedCodePass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - auto *p = new EliminateUnusedCodePass(); - return p; + return eliminateUnusedCode(F) ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char EliminateUnusedCodePass::ID = 42; -static llvm::RegisterPass P("elim-unused-code", "Eliminates unused code."); diff --git a/src/Static/Transforms/EliminateUnusedCodePass.hpp b/src/Static/Transforms/EliminateUnusedCodePass.hpp new file mode 100644 index 0000000..1b28d3e --- /dev/null +++ b/src/Static/Transforms/EliminateUnusedCodePass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_ELIMINATE_UNUSED_CODE_PASS_HPP +#define GENMC_ELIMINATE_UNUSED_CODE_PASS_HPP + +#include + +using namespace llvm; + +class EliminateUnusedCodePass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_ELIMINATE_UNUSED_CODE_PASS_HPP */ diff --git a/src/EscapeCheckerPass.cpp b/src/Static/Transforms/EscapeCheckerPass.cpp similarity index 74% rename from src/EscapeCheckerPass.cpp rename to src/Static/Transforms/EscapeCheckerPass.cpp index 272bfcc..f0eaf97 100644 --- a/src/EscapeCheckerPass.cpp +++ b/src/Static/Transforms/EscapeCheckerPass.cpp @@ -19,11 +19,12 @@ */ #include "EscapeCheckerPass.hpp" -#include "CallInfoCollectionPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" -#include "config.h" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/CallInfoCollectionPass.hpp" +#include "Support/Error.hpp" + +#include #include #include #include @@ -32,13 +33,14 @@ using namespace llvm; /* EscapeInfo impl */ -bool EscapeInfo::escapes(const Value *v) const +bool EscapeAnalysisResult::escapes(const Value *v) const { auto it = escapePoints.find(v); return it == escapePoints.cend() ? false : !it->second.empty(); } -bool EscapeInfo::escapesAfter(const Value *a, const Instruction *b, DominatorTree &DT) const +bool EscapeAnalysisResult::escapesAfter(const Value *a, const Instruction *b, + DominatorTree &DT) const { auto it = escapePoints.find(a); return it == escapePoints.cend() @@ -47,7 +49,7 @@ bool EscapeInfo::escapesAfter(const Value *a, const Instruction *b, DominatorTre [&](const Instruction *p) { return DT.dominates(b, p); }); } -Instruction *EscapeInfo::writesDynamicMemory(Value *val /*, AliasAnalysis &AA */) +auto EscapeAnalysisResult::writesDynamicMemory(Value *val /*, AliasAnalysis &AA */) -> Instruction * { auto *ptr = dyn_cast(val); if (!ptr) @@ -77,17 +79,18 @@ Instruction *EscapeInfo::writesDynamicMemory(Value *val /*, AliasAnalysis &AA */ // }); } -void EscapeInfo::calculate(llvm::Function &F, const VSet &allocFuns, - llvm::AliasAnalysis &AA) +void EscapeAnalysisResult::calculate(Function &F, const CallAnalysisResult &CAR) { + const auto &allocFuns = CAR.alloc; + /* First, collect all allocations */ - std::for_each(inst_begin(F), inst_end(F), [&](Instruction &i) { + for (auto &i : instructions(F)) { if (isAlloc(&i, &allocFuns)) - allocs.insert(&i); - }); + allocs_.insert(&i); + } /* Then, process them one by one (we need the list fixed before processing) */ - for (auto *i : allocs) { + for (auto *i : allocs_) { std::vector worklist = {i}; VSet visited; @@ -148,7 +151,7 @@ void EscapeInfo::calculate(llvm::Function &F, const VSet &allocFuns, } } -void EscapeInfo::print(llvm::raw_ostream &s) const +void EscapeAnalysisResult::print(raw_ostream &s) const { for (auto P : escapePoints) { s << P.first->getName() << " has " << P.second.size() << " escape point(s): ["; @@ -158,30 +161,20 @@ void EscapeInfo::print(llvm::raw_ostream &s) const } } -/* Pass impl */ - -void EscapeCheckerPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - au.addRequiredTransitive(); /* required but unused for now */ - au.addRequired(); - au.setPreservesAll(); -} +/* Analysis impl */ -bool EscapeCheckerPass::runOnFunction(llvm::Function &F) +auto EscapeAnalysis::run(Module &M, ModuleAnalysisManager &MAM) -> Result { - EI.calculate(F, getAnalysis().getAllocCalls(), - getAnalysis().getAAResults()); - return false; + auto &FAM = MAM.getResult(M).getManager(); + auto &CAR = MAM.getResult(M); + for (auto &F : M | std::views::filter([&](auto &F) { return !F.isDeclaration(); })) { + result_[&F].calculate(F, CAR); + } + return result_; } -llvm::Pass *createEscapeCheckerPass(bool loadsEscape /* = true */) +auto EscapeCheckerPass::run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses { - auto *p = new EscapeCheckerPass(); - p->setLoadsEscape(loadsEscape); - return p; + EAR_ = MAM.getResult(M); + return PreservedAnalyses::all(); } - -char EscapeCheckerPass::ID = 42; -static llvm::RegisterPass P("escape-checker", - "Gathers information about allocations that " - "might escape the function."); diff --git a/src/EscapeCheckerPass.hpp b/src/Static/Transforms/EscapeCheckerPass.hpp similarity index 50% rename from src/EscapeCheckerPass.hpp rename to src/Static/Transforms/EscapeCheckerPass.hpp index 58a76e2..26a9ae0 100644 --- a/src/EscapeCheckerPass.hpp +++ b/src/Static/Transforms/EscapeCheckerPass.hpp @@ -18,84 +18,87 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ESCAPE_CHECKER_PASS_HPP__ -#define __ESCAPE_CHECKER_PASS_HPP__ +#ifndef GENMC_ESCAPE_CHECKER_PASS_HPP +#define GENMC_ESCAPE_CHECKER_PASS_HPP -#include "VSet.hpp" -#include "llvm/Analysis/AliasAnalysis.h" -#include -#include -#include +#include "ADT/VSet.hpp" +#include "CallInfoCollectionPass.hpp" -#include +#include + +#include #include #include +using namespace llvm; + +class EscapeAnalysis; + /* * This class is responsible for identifying allocations that escape * their enclosing functions through writes to "global" memory. * (For the purposes of this pass, global memory is mem2reg could not * deem local. We may have to make it smarter in the future. ) */ -class EscapeInfo { +class EscapeAnalysisResult { public: - EscapeInfo() = default; - - void setLoadsEscape(bool loadsEscape) { loadsEscape = loadsEscape; } + EscapeAnalysisResult(bool loadsEscape = true) : loadsEscape_(loadsEscape) {} /* Whether we consider loads as escape points */ - bool canLoadsEscape() const { return loadsEscape; } + auto canLoadsEscape() const -> bool { return loadsEscape_; } /* (Re)-calculates the esacape points for each instruction of F */ - void calculate(llvm::Function &F, const VSet &allocFuns, - llvm::AliasAnalysis &AA); + void calculate(Function &F, const CallAnalysisResult &CAR); /* Returns true if V escapes in F */ - bool escapes(const llvm::Value *v) const; + auto escapes(const Value *v) const -> bool; /* Returns true if all escape points of A are dominated by B. * If there are no escape points, returns true. */ - bool escapesAfter(const llvm::Value *a, const llvm::Instruction *b, - llvm::DominatorTree &DT) const; + auto escapesAfter(const Value *a, const Instruction *b, DominatorTree &DT) const -> bool; /* If VAL represents local memory, returns the respective allocating instructions */ - llvm::Instruction *writesDynamicMemory(llvm::Value *val /*, llvm::AliasAnalysis &AA */); + auto writesDynamicMemory(Value *val /*, AliasAnalysis &AA */) -> Instruction *; - VSet::const_iterator alloc_begin() const { return allocs.begin(); } - VSet::const_iterator alloc_end() const { return allocs.end(); } + auto alloc_begin() const -> VSet::const_iterator { return allocs_.begin(); } + auto alloc_end() const -> VSet::const_iterator { return allocs_.end(); } /* For debugging */ - void print(llvm::raw_ostream &s) const; + void print(raw_ostream &s) const; private: - using EPT = std::unordered_map>; + using EPT = std::unordered_map>; - bool loadsEscape = true; + bool loadsEscape_ = true; EPT escapePoints; - VSet allocs; + VSet allocs_; }; /* * Populates an EscapeInfo object for the function the pass runs on. */ -class EscapeCheckerPass : public llvm::FunctionPass { - +class EscapeAnalysis : public AnalysisInfoMixin { public: - EscapeCheckerPass() : llvm::FunctionPass(ID) {} + using Result = std::unordered_map; - void setLoadsEscape(bool loadsEscape = true) { EI.setLoadsEscape(loadsEscape); } + auto run(Module &M, ModuleAnalysisManager &MAM) -> Result; - bool runOnFunction(llvm::Function &F) override; - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; +private: + friend AnalysisInfoMixin; + static inline AnalysisKey Key; + + Result result_; +}; - EscapeInfo &getEscapeInfo() { return EI; } - const EscapeInfo &getEscapeInfo() const { return EI; } +class EscapeCheckerPass : public AnalysisInfoMixin { +public: + EscapeCheckerPass(EscapeAnalysis::Result &EAR) : EAR_(EAR) {} - static char ID; + auto run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses; private: - EscapeInfo EI; + EscapeAnalysis::Result &EAR_; }; -#endif /* __ESCAPE_CHECKER_PASS_HPP__ */ +#endif /* GENMC_ESCAPE_CHECKER_PASS_HPP_ */ diff --git a/src/FunctionInlinerPass.cpp b/src/Static/Transforms/FunctionInlinerPass.cpp similarity index 66% rename from src/FunctionInlinerPass.cpp rename to src/Static/Transforms/FunctionInlinerPass.cpp index 5411804..0d3e69b 100644 --- a/src/FunctionInlinerPass.cpp +++ b/src/Static/Transforms/FunctionInlinerPass.cpp @@ -19,10 +19,10 @@ */ #include "FunctionInlinerPass.hpp" -#include "DeclareInternalsPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "MDataCollectionPass.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/Transforms/DeclareInternalsPass.hpp" +#include "Static/Transforms/MDataCollectionPass.hpp" +#include "Support/Error.hpp" #include "config.h" #include #include @@ -33,14 +33,7 @@ using namespace llvm; -void FunctionInlinerPass::getAnalysisUsage(AnalysisUsage &au) const -{ - au.addRequired(); - au.addRequired(); - au.addRequired(); -} - -bool isInlinable(CallGraph &CG, CallGraphNode *node, SmallVector &chain) +auto isInlinable(CallGraph &CG, CallGraphNode *node, SmallVector &chain) -> bool { /* Base cases: indirect/empty/recursive calls */ auto *F = node->getFunction(); @@ -60,25 +53,24 @@ bool isInlinable(CallGraph &CG, CallGraphNode *node, SmallVector bool { SmallVector chain; return isInlinable(CG, CG[&F], chain); } -bool inlineCall(CallInst *ci) +auto inlineCall(CallInst *ci) -> bool { llvm::InlineFunctionInfo ifi; #if LLVM_VERSION_MAJOR >= 11 - BUG_ON(!InlineFunction(*ci, ifi).isSuccess()); + return InlineFunction(*ci, ifi).isSuccess(); #else - BUG_ON(!InlineFunction(ci, ifi)); + return InlineFunction(ci, ifi); #endif - return true; } -bool inlineFunction(Module &M, Function *toInline) +auto inlineFunction(Module &M, Function *toInline) -> bool { std::vector calls; for (auto &F : M) { @@ -92,12 +84,14 @@ bool inlineFunction(Module &M, Function *toInline) } } - bool changed = false; - std::for_each(calls.begin(), calls.end(), [&](CallInst *ci) { changed |= inlineCall(ci); }); + auto changed = false; + for (auto *ci : calls) { + changed |= inlineCall(ci); + } return changed; } -bool FunctionInlinerPass::runOnModule(Module &M) +auto FunctionInlinerPass::run(Module &M, ModuleAnalysisManager &AM) -> PreservedAnalyses { CallGraph CG(M); @@ -107,11 +101,5 @@ bool FunctionInlinerPass::runOnModule(Module &M) changed |= inlineFunction(M, &F); } } - return changed; + return changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -ModulePass *createFunctionInlinerPass() { return new FunctionInlinerPass(); } - -char FunctionInlinerPass::ID = 42; -static llvm::RegisterPass P("function-inliner", - "Inlines all non-recursive functions."); diff --git a/src/FunctionInlinerPass.hpp b/src/Static/Transforms/FunctionInlinerPass.hpp similarity index 67% rename from src/FunctionInlinerPass.hpp rename to src/Static/Transforms/FunctionInlinerPass.hpp index c96bd5d..fa6af23 100644 --- a/src/FunctionInlinerPass.hpp +++ b/src/Static/Transforms/FunctionInlinerPass.hpp @@ -18,23 +18,20 @@ * Author: Michalis Kokologiannakis */ -#ifndef __FUNCTION_INLINER_PASS_HPP__ -#define __FUNCTION_INLINER_PASS_HPP__ +#ifndef GENMC_FUNCTION_INLINER_PASS_HPP +#define GENMC_FUNCTION_INLINER_PASS_HPP + +#include +#include +#include #include -#include -class FunctionInlinerPass : public llvm::ModulePass { +using namespace llvm; +class FunctionInlinerPass : public PassInfoMixin { public: - FunctionInlinerPass() : llvm::ModulePass(ID) {} - - virtual bool runOnModule(llvm::Module &M); - void getAnalysisUsage(llvm::AnalysisUsage &au) const; - - static char ID; - -private: + auto run(Module &M, ModuleAnalysisManager &AM) -> PreservedAnalyses; }; -#endif /* __FUNCTION_INLINER_PASS_HPP__ */ +#endif /* GENMC_FUNCTION_INLINER_PASS_HPP */ diff --git a/src/InstAnnotator.cpp b/src/Static/Transforms/InstAnnotator.cpp similarity index 98% rename from src/InstAnnotator.cpp rename to src/Static/Transforms/InstAnnotator.cpp index b16adb7..614a1a6 100644 --- a/src/InstAnnotator.cpp +++ b/src/Static/Transforms/InstAnnotator.cpp @@ -21,10 +21,10 @@ #include "config.h" #include "InstAnnotator.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" -#include "ModuleInfo.hpp" -#include "SExprVisitor.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/ModuleInfo.hpp" +#include "Support/SExprVisitor.hpp" #include #include #include @@ -61,10 +61,11 @@ InstAnnotator::IRExprUP InstAnnotator::generateOperandExpr(Value *op) if (auto *c = dyn_cast(op)) { if (isa(c)) { return ConcreteExpr::create(c->getType()->getIntegerBitWidth(), - 42); + SVal(42)); } else if (c->getType()->isIntegerTy()) { auto v = c->getUniqueInteger(); - return ConcreteExpr::create(v.getBitWidth(), v.getLimitedValue()); + return ConcreteExpr::create(v.getBitWidth(), + SVal(v.getLimitedValue())); } else if (isa(c)) { BUG_ON(!op->getType()->isPointerTy()); auto iIt = @@ -76,7 +77,7 @@ InstAnnotator::IRExprUP InstAnnotator::generateOperandExpr(Value *op) dyn_cast(*iIt)->getParent()->getParent()->getParent(); auto &DL = mod->getDataLayout(); return ConcreteExpr::create( - DL.getTypeAllocSizeInBits(op->getType()), 0); + DL.getTypeAllocSizeInBits(op->getType()), SVal(0)); } ERROR("Only integer and null constants currently allowed in assume() " "expressions.\n"); diff --git a/src/InstAnnotator.hpp b/src/Static/Transforms/InstAnnotator.hpp similarity index 96% rename from src/InstAnnotator.hpp rename to src/Static/Transforms/InstAnnotator.hpp index 810bff6..119c682 100644 --- a/src/InstAnnotator.hpp +++ b/src/Static/Transforms/InstAnnotator.hpp @@ -18,11 +18,11 @@ * Author: Michalis Kokologiannakis */ -#ifndef __INST_ANNOTATOR_HPP__ -#define __INST_ANNOTATOR_HPP__ +#ifndef GENMC_INST_ANNOTATOR_HPP +#define GENMC_INST_ANNOTATOR_HPP -#include "Error.hpp" -#include "VSet.hpp" +#include "ADT/VSet.hpp" +#include "Support/Error.hpp" #include #include #include @@ -114,4 +114,4 @@ class InstAnnotator { InstAnnotMap annotMap; }; -#endif /* __INST_ANNOTATOR_HPP__ */ +#endif /* GENMC_INST_ANNOTATOR_HPP */ diff --git a/src/IntrinsicLoweringPass.cpp b/src/Static/Transforms/IntrinsicLoweringPass.cpp similarity index 70% rename from src/IntrinsicLoweringPass.cpp rename to src/Static/Transforms/IntrinsicLoweringPass.cpp index 839a8c8..e20f6de 100644 --- a/src/IntrinsicLoweringPass.cpp +++ b/src/Static/Transforms/IntrinsicLoweringPass.cpp @@ -19,8 +19,10 @@ */ #include "IntrinsicLoweringPass.hpp" -#include "config.h" + #include +#include +#include #include #include #include @@ -30,11 +32,14 @@ #include #include -bool IntrinsicLoweringPass::runOnBasicBlock(llvm::BasicBlock &BB, llvm::Module &M) +using namespace llvm; + +auto runOnBasicBlock(BasicBlock &BB, IntrinsicLowering *IL) -> bool { - bool modified = false; + auto &M = *BB.getParent()->getParent(); + auto modified = false; for (auto it = BB.begin(); it != BB.end();) { - llvm::IntrinsicInst *I = llvm::dyn_cast(&*it); + auto *I = llvm::dyn_cast(&*it); /* Iterator is incremented in order for it not to be invalidated */ ++it; /* If the instruction is not an intrinsic call, skip it */ @@ -58,7 +63,13 @@ bool IntrinsicLoweringPass::runOnBasicBlock(llvm::BasicBlock &BB, llvm::Module & modified = true; break; case llvm::Intrinsic::trap: { - /* Lower calls to @llvm.trap to abort() calls */ + /* + * Check for calls to @llvm.trap. Such calls may occur if LLVM + * detects a NULL pointer dereference in the CFG and simplify + * it to a trap call. In order for this to happen, the program + * has to be compiled with -O1 or -O2. + * We lower such calls to abort() (@trap could also be erased from M) + */ auto FC = M.getOrInsertFunction("abort", llvm::Type::getVoidTy(M.getContext())); #if LLVM_VERSION_MAJOR < 9 @@ -84,34 +95,14 @@ bool IntrinsicLoweringPass::runOnBasicBlock(llvm::BasicBlock &BB, llvm::Module & return modified; } -bool IntrinsicLoweringPass::runOnModule(llvm::Module &M) +auto IntrinsicLoweringPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - bool modified = false; - /* Scan through the instructions and lower intrinsic calls */ - for (auto &F : M) - for (auto &BB : F) - modified |= runOnBasicBlock(BB, M); + auto ILUP = std::make_unique(F.getParent()->getDataLayout()); - /* - * Check for calls to @llvm.trap. Such calls may occur if LLVM - * detects a NULL pointer dereference in the CFG and simplify - * it to a trap call. In order for this to happen, the program - * has to be compiled with -O1 or -O2. - */ - if (llvm::Function *trapDecl = M.getFunction("llvm.trap")) { - trapDecl->eraseFromParent(); - modified = true; - } - return modified; -} + /* Scan through the instructions and lower intrinsic calls */ + auto modified = false; + for (auto &BB : F) + modified |= runOnBasicBlock(BB, &*ILUP); -llvm::ModulePass *createIntrinsicLoweringPass(llvm::Module &M) -{ -#ifdef LLVM_EXECUTIONENGINE_DATALAYOUT_PTR - return new IntrinsicLoweringPass(*M.getDataLayout()); -#else - return new IntrinsicLoweringPass(M.getDataLayout()); -#endif + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char IntrinsicLoweringPass::ID = 42; diff --git a/src/Static/Transforms/IntrinsicLoweringPass.hpp b/src/Static/Transforms/IntrinsicLoweringPass.hpp new file mode 100644 index 0000000..0398dfa --- /dev/null +++ b/src/Static/Transforms/IntrinsicLoweringPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_INTRINSIC_LOWERING_PASS_HPP +#define GENMC_INTRINSIC_LOWERING_PASS_HPP + +#include + +using namespace llvm; + +class IntrinsicLoweringPass : public PassInfoMixin { +public: + auto run(Function &M, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_INTRINSIC_LOWERING_PASS_HPP */ diff --git a/src/LoadAnnotationPass.cpp b/src/Static/Transforms/LoadAnnotationPass.cpp similarity index 78% rename from src/LoadAnnotationPass.cpp rename to src/Static/Transforms/LoadAnnotationPass.cpp index e90c83f..90e7a0b 100644 --- a/src/LoadAnnotationPass.cpp +++ b/src/Static/Transforms/LoadAnnotationPass.cpp @@ -18,21 +18,17 @@ * Author: Michalis Kokologiannakis */ -#include "config.h" - -#include "Error.hpp" -#include "InstAnnotator.hpp" -#include "LLVMUtils.hpp" #include "LoadAnnotationPass.hpp" -#include "SExpr.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/InstAnnotator.hpp" +#include "Support/Error.hpp" +#include "Support/SExpr.hpp" #include #include #include using namespace llvm; -void LoadAnnotationPass::getAnalysisUsage(llvm::AnalysisUsage &au) const { au.setPreservesAll(); } - /* Helper for getSourceLoads() -- see below */ void calcSourceLoads(Instruction *i, VSet phis, std::vector &source) { @@ -71,10 +67,13 @@ void calcSourceLoads(Instruction *i, VSet phis, std::vector LoadAnnotationPass::getSourceLoads(CallInst *assm) const +/* + * Returns the source loads of an assume statement, that is, + * loads the result of which is used in the assume. + */ +auto getSourceLoads(CallInst *assm) -> std::vector { VSet phis; std::vector source; @@ -86,9 +85,11 @@ std::vector LoadAnnotationPass::getSourceLoads(CallInst *assm) co return source; } -std::vector -LoadAnnotationPass::filterAnnotatableFromSource(CallInst *assm, - const std::vector &source) const +/* + * Given an assume's source loads, returns the annotatable ones. + */ +auto filterAnnotatableFromSource(CallInst *assm, const std::vector &source) + -> std::vector { std::vector result; @@ -125,16 +126,19 @@ LoadAnnotationPass::filterAnnotatableFromSource(CallInst *assm, return result; } -std::vector LoadAnnotationPass::getAnnotatableLoads(CallInst *assm) const +/* + * Returns all of ASSM's annotatable loads + */ +auto getAnnotatableLoads(CallInst *assm) -> std::vector { if (!isAssumeFunction(getCalledFunOrStripValName(*assm))) - return std::vector(); /* yet another check... */ + return {}; /* yet another check... */ auto sourceLoads = getSourceLoads(assm); return filterAnnotatableFromSource(assm, sourceLoads); } -bool LoadAnnotationPass::runOnFunction(llvm::Function &F) +auto LoadAnnotationAnalysis::run(Function &F, FunctionAnalysisManager &FAM) -> Result { InstAnnotator annotator; @@ -143,19 +147,16 @@ bool LoadAnnotationPass::runOnFunction(llvm::Function &F) if (isAssumeFunction(getCalledFunOrStripValName(*a))) { auto loads = getAnnotatableLoads(a); for (auto *l : loads) { - LAI.annotMap[l] = annotator.annotate(l); + result_.annotMap[l] = annotator.annotate(l); } } } } - return false; + return result_; } -FunctionPass *createLoadAnnotationPass(AnnotationInfo &LAI) +auto LoadAnnotationPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - return new LoadAnnotationPass(LAI); + LAI_ = FAM.getResult(F); + return PreservedAnalyses::all(); } - -char LoadAnnotationPass::ID = 42; -// static llvm::RegisterPass P("annotate-loads", -// "Annotates loads used by assume() statements."); diff --git a/src/Static/Transforms/LoadAnnotationPass.hpp b/src/Static/Transforms/LoadAnnotationPass.hpp new file mode 100644 index 0000000..dcffd3d --- /dev/null +++ b/src/Static/Transforms/LoadAnnotationPass.hpp @@ -0,0 +1,55 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_LOAD_ANNOTATION_PASS_HPP +#define GENMC_LOAD_ANNOTATION_PASS_HPP + +#include "Static/ModuleInfo.hpp" +#include +#include + +using namespace llvm; + +using LoadAnnotationAnalysisResult = AnnotationInfo; + +class LoadAnnotationAnalysis : public AnalysisInfoMixin { +public: + using Result = LoadAnnotationAnalysisResult; + + auto run(Function &F, FunctionAnalysisManager &FAM) -> Result; + +private: + friend AnalysisInfoMixin; + static inline AnalysisKey Key; + + Result result_; +}; + +class LoadAnnotationPass : public AnalysisInfoMixin { +public: + LoadAnnotationPass(LoadAnnotationAnalysisResult &LAI) : LAI_(LAI) {} + + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; + +private: + LoadAnnotationAnalysisResult &LAI_; +}; + +#endif /* GENMC_LOAD_ANNOTATION_PASS_HPP_ */ diff --git a/src/LocalSimplifyCFGPass.cpp b/src/Static/Transforms/LocalSimplifyCFGPass.cpp similarity index 79% rename from src/LocalSimplifyCFGPass.cpp rename to src/Static/Transforms/LocalSimplifyCFGPass.cpp index e07611f..6ef1c60 100644 --- a/src/LocalSimplifyCFGPass.cpp +++ b/src/Static/Transforms/LocalSimplifyCFGPass.cpp @@ -19,9 +19,9 @@ */ #include "LocalSimplifyCFGPass.hpp" -#include "EliminateCASPHIsPass.hpp" -#include "Error.hpp" -#include "LLVMUtils.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/EliminateCASPHIsPass.hpp" +#include "Support/Error.hpp" #include "config.h" #include @@ -35,12 +35,7 @@ using namespace llvm; -void LocalSimplifyCFGPass::getAnalysisUsage(AnalysisUsage &au) const -{ - au.addRequired(); -} - -static bool foldSuccessors(BasicBlock *bb) +static auto foldSuccessors(BasicBlock *bb) -> bool { auto *bi = dyn_cast(bb->getTerminator()); if (!bi || !bi->isConditional()) @@ -50,7 +45,7 @@ static bool foldSuccessors(BasicBlock *bb) tryThreadSuccessor(bi, bi->getSuccessor(1)); } -static bool localSimplifyCFG(Function &F) +static auto localSimplifyCFG(Function &F) -> bool { auto modified = false; @@ -84,14 +79,7 @@ static bool localSimplifyCFG(Function &F) return modified; } -bool LocalSimplifyCFGPass::runOnFunction(Function &F) { return localSimplifyCFG(F); } - -Pass *createLocalSimplifyCFGPass() +auto LocalSimplifyCFGPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - auto *p = new LocalSimplifyCFGPass(); - return p; + return localSimplifyCFG(F) ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char LocalSimplifyCFGPass::ID = 42; -static llvm::RegisterPass - P("local-simplify-cfg", "Performs some local simplifications to the CFG."); diff --git a/src/Static/Transforms/LocalSimplifyCFGPass.hpp b/src/Static/Transforms/LocalSimplifyCFGPass.hpp new file mode 100644 index 0000000..be87966 --- /dev/null +++ b/src/Static/Transforms/LocalSimplifyCFGPass.hpp @@ -0,0 +1,33 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_LOCAL_SIMPLIFY_CFG_PASS_HPP +#define GENMC_LOCAL_SIMPLIFY_CFG_PASS_HPP + +#include + +using namespace llvm; + +class LocalSimplifyCFGPass : public PassInfoMixin { +public: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; +}; + +#endif /* GENMC_LOCAL_SIMPLIFY_CFG_PASS_HPP */ diff --git a/src/LoopJumpThreadingPass.cpp b/src/Static/Transforms/LoopJumpThreadingPass.cpp similarity index 81% rename from src/LoopJumpThreadingPass.cpp rename to src/Static/Transforms/LoopJumpThreadingPass.cpp index 1dfc94c..77d564a 100644 --- a/src/LoopJumpThreadingPass.cpp +++ b/src/Static/Transforms/LoopJumpThreadingPass.cpp @@ -19,29 +19,24 @@ */ #include "LoopJumpThreadingPass.hpp" -#include "InstAnnotator.hpp" -#include "LLVMUtils.hpp" -#include "SExprVisitor.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/InstAnnotator.hpp" +#include "Support/SExprVisitor.hpp" #include #include using namespace llvm; -void LoopJumpThreadingPass::getAnalysisUsage(AnalysisUsage &au) const -{ - LoopPass::getAnalysisUsage(au); -} - -bool inLoopBody(Loop *l, BasicBlock *bb) { return l->contains(bb) && bb != l->getHeader(); } +auto inLoopBody(Loop *l, BasicBlock *bb) -> bool { return l->contains(bb) && bb != l->getHeader(); } -bool isNonTrivialUser(User *u, PHINode *criticalPHI) +auto isNonTrivialUser(User *u, PHINode *criticalPHI) -> bool { auto *p = dyn_cast(u); return !p || std::any_of(p->user_begin(), p->user_end(), [criticalPHI](User *us) { return us != criticalPHI; }); } -bool isCriticalPHIUsedTrivially(Loop *l, PHINode *criticalPHI) +auto isCriticalPHIUsedTrivially(Loop *l, PHINode *criticalPHI) -> bool { return std::none_of(criticalPHI->user_begin(), criticalPHI->user_end(), [&](User *u) { auto *p = dyn_cast(u)->getParent(); @@ -52,7 +47,7 @@ bool isCriticalPHIUsedTrivially(Loop *l, PHINode *criticalPHI) }); } -bool areNonCriticalPHIsUsedInBody(Loop *l, PHINode *criticalPHI) +auto areNonCriticalPHIsUsedInBody(Loop *l, PHINode *criticalPHI) -> bool { for (auto &phi : l->getHeader()->phis()) { if (&phi == criticalPHI) @@ -75,13 +70,13 @@ bool areNonCriticalPHIsUsedInBody(Loop *l, PHINode *criticalPHI) * are OK because if we prove that the header always jumps to the body, * then these uses can be replaced with the initial value. */ -bool loopUsesHeaderPHIsTrivially(Loop *l, PHINode *criticalPHI) +auto loopUsesHeaderPHIsTrivially(Loop *l, PHINode *criticalPHI) -> bool { return isCriticalPHIUsedTrivially(l, criticalPHI) && !areNonCriticalPHIsUsedInBody(l, criticalPHI); } -PHINode *getPHIConstEntryValueUsedInCond(Loop *l) +auto getPHIConstEntryValueUsedInCond(Loop *l) -> PHINode * { for (auto iit = l->getHeader()->begin(); auto phi = dyn_cast(iit); ++iit) { for (auto &v : phi->incoming_values()) { @@ -95,7 +90,7 @@ PHINode *getPHIConstEntryValueUsedInCond(Loop *l) return nullptr; } -std::unique_ptr> generateExprJumpsToBody(Loop *l) +auto generateExprJumpsToBody(Loop *l) -> std::unique_ptr> { auto condExp = InstAnnotator().annotateBBCond(l->getHeader(), l->getLoopPredecessor()); auto *bi = dyn_cast(l->getHeader()->getTerminator()); @@ -107,7 +102,7 @@ std::unique_ptr> generateExprJumpsToBody(Loop *l) return NotExpr::create(std::move(condExp)); } -bool entryAlwaysJumpsToBody(Loop *l) +auto entryAlwaysJumpsToBody(Loop *l) -> bool { /* Make sure that the header (conditionally) jumps at the body */ auto *h = l->getHeader(); @@ -125,7 +120,7 @@ bool entryAlwaysJumpsToBody(Loop *l) return (numSeen == 0) && res.getBool(); } -bool invertLoop(Loop *l, PHINode *criticalPHI) +auto invertLoop(Loop *l, PHINode *criticalPHI) -> bool { auto *ph = l->getLoopPredecessor(); auto *phbi = dyn_cast(ph->getTerminator()); @@ -178,31 +173,27 @@ bool invertLoop(Loop *l, PHINode *criticalPHI) return true; } -bool LoopJumpThreadingPass::runOnLoop(Loop *l, LPPassManager &lpm) +auto LoopJumpThreadingPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, + LPMUpdater &U) -> PreservedAnalyses { /* The whole point is to get rid of Φ-nodes in the header... */ - if (!isa(*l->getHeader()->begin())) - return false; + if (!isa(L.getHeader()->begin())) + return PreservedAnalyses::all(); /* If the header has multiple predecessors, skip */ - if (!l->getLoopPredecessor()) - return false; + if (!L.getLoopPredecessor()) + return PreservedAnalyses::all(); /* * The header needs to have at least one constant incoming * from the entry, so that we can evaluate the header condition */ - auto *criticalPHI = getPHIConstEntryValueUsedInCond(l); + auto *criticalPHI = getPHIConstEntryValueUsedInCond(&L); if (!criticalPHI) - return false; + return PreservedAnalyses::all(); - if (entryAlwaysJumpsToBody(l)) - return invertLoop(l, criticalPHI); - return false; + if (entryAlwaysJumpsToBody(&L)) + return invertLoop(&L, criticalPHI) ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + return PreservedAnalyses::all(); } - -Pass *createLoopJumpThreadingPass() { return new LoopJumpThreadingPass(); } - -char LoopJumpThreadingPass::ID = 42; -static RegisterPass P("loop-jump-threading", - "Performs jump threading for simple loop headers."); diff --git a/src/Static/Transforms/LoopJumpThreadingPass.hpp b/src/Static/Transforms/LoopJumpThreadingPass.hpp new file mode 100644 index 0000000..9ec6f68 --- /dev/null +++ b/src/Static/Transforms/LoopJumpThreadingPass.hpp @@ -0,0 +1,34 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#ifndef GENMC_LOOP_THREAD_JUMPING_PASS_HPP +#define GENMC_LOOP_THREAD_JUMPING_PASS_HPP + +#include + +using namespace llvm; + +class LoopJumpThreadingPass : public PassInfoMixin { +public: + auto run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) + -> PreservedAnalyses; +}; + +#endif /* GENMC_LOOP_THREAD_JUMPING_PASS_HPP */ diff --git a/src/LoopUnrollPass.cpp b/src/Static/Transforms/LoopUnrollPass.cpp similarity index 70% rename from src/LoopUnrollPass.cpp rename to src/Static/Transforms/LoopUnrollPass.cpp index 9340445..4db1c10 100644 --- a/src/LoopUnrollPass.cpp +++ b/src/Static/Transforms/LoopUnrollPass.cpp @@ -20,16 +20,13 @@ #include "config.h" -#include "DeclareInternalsPass.hpp" -#include "Error.hpp" +#include "ADT/VSet.hpp" #include "LoopUnrollPass.hpp" -#include "VSet.hpp" +#include "Static/Transforms/DeclareInternalsPass.hpp" +#include "Support/Error.hpp" #include #include #include -#ifdef LLVM_ALLOCAINST_TAKES_ALIGN -#include -#endif #include #if LLVM_VERSION_MAJOR < 8 @@ -52,19 +49,12 @@ typedef llvm::Instruction TerminatorInst; using namespace llvm; -void LoopUnrollPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - LoopPass::getAnalysisUsage(au); - au.addRequired(); - au.addPreserved(); -} - /* * Returns a PHI node the only purpose of which is to serve as the * bound variable for this loop. It does not set up the arguments for * the PHI node. */ -PHINode *createBoundInit(Loop *l) +auto createBoundInit(Loop *l) -> PHINode * { Function *parentFun = (*l->block_begin())->getParent(); Type *int32Typ = Type::getInt32Ty(parentFun->getContext()); @@ -77,7 +67,7 @@ PHINode *createBoundInit(Loop *l) * Returns an instruction which decrements the bound variable for this loop (BOUNDVAL). * The returned value should be later checked in order to bound the loop. */ -BinaryOperator *createBoundDecrement(Loop *l, PHINode *boundVal) +auto createBoundDecrement(Loop *l, PHINode *boundVal) -> BinaryOperator * { Function *parentFun = (*l->block_begin())->getParent(); Type *int32Typ = Type::getInt32Ty(parentFun->getContext()); @@ -100,34 +90,25 @@ void addBoundCmpAndSpinEndBefore(Loop *l, PHINode *val, BinaryOperator *decVal) BUG_ON(!endLoopFun); CallInst::Create(endLoopFun, {cmp}, "", decVal); - return; } -bool LoopUnrollPass::runOnLoop(Loop *l, LPPassManager &lpm) +auto LoopUnrollPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, + LPMUpdater &U) -> PreservedAnalyses { - if (!shouldUnroll(l)) - return false; + if (!shouldUnroll(&L)) + return PreservedAnalyses::all(); - PHINode *val = createBoundInit(l); - BinaryOperator *dec = createBoundDecrement(l, val); - Type *int32Typ = Type::getInt32Ty((*l->block_begin())->getParent()->getContext()); + PHINode *val = createBoundInit(&L); + BinaryOperator *dec = createBoundDecrement(&L, val); + Type *int32Typ = Type::getInt32Ty((*L.block_begin())->getParent()->getContext()); /* Adjust incoming values for the bound variable */ - for (BasicBlock *bb : predecessors(l->getHeader())) - val->addIncoming(l->contains(bb) ? (Value *)dec - : (Value *)ConstantInt::get(int32Typ, unrollDepth), + for (BasicBlock *bb : predecessors(L.getHeader())) + val->addIncoming(L.contains(bb) ? (Value *)dec + : (Value *)ConstantInt::get(int32Typ, unrollDepth_), bb); /* Finally, compare the bound and block if it reaches zero */ - addBoundCmpAndSpinEndBefore(l, val, dec); - return true; + addBoundCmpAndSpinEndBefore(&L, val, dec); + return PreservedAnalyses::none(); } - -Pass *createLoopUnrollPass(unsigned int depth, const VSet &noUnrollFuns /* = {} */) -{ - return new LoopUnrollPass(depth, noUnrollFuns); -} - -char LoopUnrollPass::ID = 42; -// static RegisterPass P("loop-unroll", -// "Unrolls all loops at LLVM-IR level."); diff --git a/src/LoopUnrollPass.hpp b/src/Static/Transforms/LoopUnrollPass.hpp similarity index 54% rename from src/LoopUnrollPass.hpp rename to src/Static/Transforms/LoopUnrollPass.hpp index 26bf73d..034f279 100644 --- a/src/LoopUnrollPass.hpp +++ b/src/Static/Transforms/LoopUnrollPass.hpp @@ -18,39 +18,33 @@ * Author: Michalis Kokologiannakis */ -#ifndef __LOOP_UNROLL_PASS_HPP__ -#define __LOOP_UNROLL_PASS_HPP__ - -#include "VSet.hpp" -#include "config.h" -#include -#ifdef LLVM_PASS_GETPASSNAME_IS_STRINGREF -#include -#endif +#ifndef GENMC_LOOP_UNROLL_PASS_HPP +#define GENMC_LOOP_UNROLL_PASS_HPP + +#include "ADT/VSet.hpp" #include #include -#include +#include -class LoopUnrollPass : public llvm::LoopPass { +using namespace llvm; +class LoopUnrollPass : public PassInfoMixin { public: - static char ID; - LoopUnrollPass(unsigned int depth, const VSet &noUnrollFuns = {}) - : llvm::LoopPass(ID), unrollDepth(depth), noUnroll(noUnrollFuns){}; + : unrollDepth_(depth), noUnroll_(noUnrollFuns) + {} + + auto run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) + -> PreservedAnalyses; - bool shouldUnroll(llvm::Loop *l) const +private: + auto shouldUnroll(llvm::Loop *l) const -> bool { - return !noUnroll.count((*l->block_begin())->getParent()->getName().str()); + return !noUnroll_.count((*l->block_begin())->getParent()->getName().str()); } - virtual llvm::StringRef getPassName() const { return "LoopUnrollPass"; } - virtual void getAnalysisUsage(llvm::AnalysisUsage &au) const; - virtual bool runOnLoop(llvm::Loop *l, llvm::LPPassManager &LPM); - -private: - unsigned int unrollDepth; - VSet noUnroll; + unsigned int unrollDepth_{}; + VSet noUnroll_; }; -#endif /* __LOOP_UNROLL_PASS_HPP__ */ +#endif /* GENMC_LOOP_UNROLL_PASS_HPP */ diff --git a/src/Static/Transforms/MDataCollectionPass.cpp b/src/Static/Transforms/MDataCollectionPass.cpp new file mode 100644 index 0000000..141ec3c --- /dev/null +++ b/src/Static/Transforms/MDataCollectionPass.cpp @@ -0,0 +1,209 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +#include "MDataCollectionPass.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +void collectVarName(Module &M, unsigned int ptr, Type *typ, DIType *dit, std::string nameBuilder, + NameInfo &info) +{ + if (!isa(typ) && !isa(typ) && !isa(typ)) { + info.addOffsetInfo(ptr, nameBuilder); + return; + } + + unsigned int offset = 0; + if (auto *AT = dyn_cast(typ)) { + auto *newDit = dit; + if (auto *dict = dyn_cast(dit)) { + newDit = (!dict->getBaseType()) + ? dict + : llvm::dyn_cast(dict->getBaseType()); + } + auto elemSize = M.getDataLayout().getTypeAllocSize(AT->getElementType()); + for (auto i = 0u; i < AT->getNumElements(); i++) { + collectVarName(M, ptr + offset, AT->getElementType(), newDit, + nameBuilder + "[" + std::to_string(i) + "]", info); + offset += elemSize; + } + } else if (auto *ST = dyn_cast(typ)) { + DINodeArray dictElems; + + /* Since this is a struct type, the metadata should yield a + * composite type, or a derived type that will eventually + * yield a composite type. */ + if (auto *dict = dyn_cast(dit)) { + dictElems = dict->getElements(); + } + if (auto *dict = dyn_cast(dit)) { + DIType *dbt = dict; + while (auto *dbtc = dyn_cast(dbt)) + dbt = dyn_cast(dbtc->getBaseType()); + + if (auto *dbtc = dyn_cast(dbt)) + dictElems = dbtc->getElements(); + else { + /* Take some precautions, in case we got this + * metadata thing all wrong... */ + PRINT_BUGREPORT_INFO_ONCE("struct-mdata", + "Cannot get variable naming info"); + return; + } + } + + /* It can be dictElems.size() < ST->getNumElements(), e.g., for va_arg */ + auto i = 0u; + auto minSize = std::min(dictElems.size(), ST->getNumElements()); + for (auto it = ST->element_begin(); i < minSize; ++it, ++i) { + auto elemSize = M.getDataLayout().getTypeAllocSize(*it); + auto didt = dictElems[i]; + if (auto *dit = dyn_cast(didt)) { + if (auto ditb = dyn_cast(dit->getBaseType())) + collectVarName(M, ptr + offset, *it, ditb, + nameBuilder + "." + dit->getName().str(), + info); + } + offset += elemSize; + } + } else { + BUG(); + } +} + +auto collectVarName(Module &M, Type *typ, DIType *dit) -> NameInfo +{ + NameInfo info; + collectVarName(M, 0, typ, dit, "", info); + return info; +} + +void MDataInfo::collectGlobalInfo(GlobalVariable &v, Module &M) +{ + /* If we already have data for the variable, skip */ + if (hasGlobalInfo(&v)) + return; + + auto &info = getGlobalInfo(&v); + info = std::make_shared(); + + if (!v.getMetadata("dbg")) + return; + + BUG_ON(!isa(v.getMetadata("dbg"))); + auto *dive = static_cast(v.getMetadata("dbg")); + auto dit = dive->getVariable()->getType(); + + /* Check whether it is a global pointer */ + if (auto *ditc = dyn_cast(dit)) + *info = collectVarName(M, v.getValueType(), ditc); +} + +void MDataInfo::collectLocalInfo(DbgDeclareInst *DD, Module &M) +{ + /* Skip if it's not an alloca or we don't have data */ + auto *v = dyn_cast(DD->getAddress()); + if (!v) + return; + + if (hasLocalInfo(v)) + return; + + auto &info = getLocalInfo(v); + info = std::make_shared(); + + /* Store alloca's metadata, in case it's used in memcpy */ + allocaMData[v] = DD->getVariable(); + + auto dit = DD->getVariable()->getType(); + if (auto *ditc = dyn_cast(dit)) + *info = collectVarName(M, v->getAllocatedType(), ditc); +} + +void MDataInfo::collectMemCpyInfo(MemCpyInst *mi, Module &M) +{ + /* + * Only mark global variables w/ private linkage that will + * otherwise go undetected by this pass + */ + auto *src = dyn_cast(mi->getSource()); + if (!src) + return; + + if (hasGlobalInfo(src)) + return; + + auto &info = getGlobalInfo(src); + info = std::make_shared(); + + /* + * Since there will be no metadata for variables with private linkage, + * we do a small hack and take the metadata of memcpy()'s dest for + * memcpy()'s source + * The type of the dest is guaranteed to be a pointer + */ + auto *dst = dyn_cast(mi->getDest()); + BUG_ON(!dst); + + if (allocaMData.count(dst) == 0) + return; /* We did our best, but couldn't get a name for it... */ + auto dit = allocaMData[dst]->getType(); + if (auto *ditc = dyn_cast(dit)) + *info = collectVarName(M, dst->getAllocatedType(), ditc); +} + +auto MDataInfo::run(Module &M, ModuleAnalysisManager &AM) -> Result +{ + /* First, get type information for user's global variables */ + for (auto &v : GLOBALS(M)) + collectGlobalInfo(v, M); + + /* Then for all local variables and some other special cases */ + for (auto &F : M) { + for (auto &I : instructions(F)) { + if (auto *dd = dyn_cast(&I)) + collectLocalInfo(dd, M); + if (auto *mi = dyn_cast(&I)) + collectMemCpyInfo(mi, M); + } + } + return PMI; +} + +auto MDataCollectionPass::run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses +{ + PMI = MAM.getResult(M); + return PreservedAnalyses::all(); +} diff --git a/src/MDataCollectionPass.hpp b/src/Static/Transforms/MDataCollectionPass.hpp similarity index 54% rename from src/MDataCollectionPass.hpp rename to src/Static/Transforms/MDataCollectionPass.hpp index 7474b57..e8e6739 100644 --- a/src/MDataCollectionPass.hpp +++ b/src/Static/Transforms/MDataCollectionPass.hpp @@ -18,91 +18,98 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MDATA_COLLECTION_PASS_HPP__ -#define __MDATA_COLLECTION_PASS_HPP__ +#ifndef GENMC_MDATA_COLLECTION_PASS_HPP +#define GENMC_MDATA_COLLECTION_PASS_HPP -#include "ModuleInfo.hpp" -#include "NameInfo.hpp" +#include "Static/ModuleInfo.hpp" +#include "Support/NameInfo.hpp" #include #include #include #include +#include + #include #include #include -class MDataCollectionPass : public llvm::ModulePass { - -public: - static char ID; - - MDataCollectionPass() : llvm::ModulePass(ID) {} +using namespace llvm; - void setPassModuleInfo(PassModuleInfo *I) { PI = I; } +class MDataInfo : public AnalysisInfoMixin { - virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; - virtual bool runOnModule(llvm::Module &M) override; +public: + using Result = PassModuleInfo; + auto run(Module &M, ModuleAnalysisManager &AM) -> Result; -protected: - void collectVarName(llvm::Module &M, unsigned int ptr, llvm::Type *typ, llvm::DIType *dit, - std::string nameBuilder, NameInfo &names); + auto collectMData(Module &M) -> MDataInfo::Result; +private: /* Collects name info for a global variable */ void collectGlobalInfo(llvm::GlobalVariable &v, llvm::Module &M); /* Collects name info for a stack variable */ void collectLocalInfo(llvm::DbgDeclareInst *DD, llvm::Module &M); - /* Collect name info for internal types */ - void collectInternalInfo(llvm::Module &M); - - /* Collect info about the files used */ - void collectFilenameInfo(llvm::CallInst *DD, llvm::Module &M); - /* * Collects name info about global variables w/ private linkage * used in memory intrinsics */ void collectMemCpyInfo(llvm::MemCpyInst *MI, llvm::Module &M); - /* Marks V's name as used in the module. - * Reports an error if the name is not a constant */ - void initializeFilenameEntry(llvm::Value *v); - /* Check whether the respective information exist */ - bool hasGlobalInfo(llvm::Value *gv) const { return PI->varInfo.globalInfo[gv].get(); } - bool hasLocalInfo(llvm::Value *lv) const { return PI->varInfo.localInfo[lv].get(); } - bool hasInternalInfo(const std::string &key) const + auto hasGlobalInfo(llvm::Value *gv) const -> bool + { + return PMI.varInfo.globalInfo.contains(gv); + } + auto hasLocalInfo(llvm::Value *lv) const -> bool { - return PI->varInfo.internalInfo[key].get(); + return PMI.varInfo.localInfo.contains(lv); + } + auto hasInternalInfo(const std::string &key) const -> bool + { + return PMI.varInfo.internalInfo.contains(key); } /* Getters for collected naming info */ - std::shared_ptr &getGlobalInfo(llvm::Value *gv) + auto getGlobalInfo(llvm::Value *gv) -> std::shared_ptr & { - return PI->varInfo.globalInfo[gv]; + return PMI.varInfo.globalInfo[gv]; } - std::shared_ptr &getLocalInfo(llvm::Value *lv) + auto getLocalInfo(llvm::Value *lv) -> std::shared_ptr & { - return PI->varInfo.localInfo[lv]; + return PMI.varInfo.localInfo[lv]; } - std::shared_ptr &getInternalInfo(const std::string &key) + auto getInternalInfo(const std::string &key) -> std::shared_ptr & { - return PI->varInfo.internalInfo[key]; + return PMI.varInfo.internalInfo[key]; } - void collectFilename(const std::string &name) { PI->filenames.insert(name); } + void collectFilename(const std::string &name) { PMI.filenames.insert(name); } + + friend AnalysisInfoMixin; + static inline AnalysisKey Key; -private: /* Maps allocas to the metadata of the variable allocated */ std::unordered_map allocaMData; + PassModuleInfo PMI; +}; + +class MDataCollectionPass : public AnalysisInfoMixin { +public: + MDataCollectionPass(PassModuleInfo &PMI) : PMI(PMI) {} + + auto run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses; + +private: + MDataInfo info{}; + /* We have to extract the necessary information out of this pass. * If we try to get them in another pass (e.g., w/ getAnalysis()), * then a new instance of this pass may be created (e.g., if the pass * gets invalidated), and we will lose all the data we have collected. */ - PassModuleInfo *PI = nullptr; + PassModuleInfo &PMI; }; -#endif /* __MDATA_COLLECTION_PASS_HPP__ */ +#endif /* GENMC_MDATA_COLLECTION_PASS_HPP */ diff --git a/src/MMDetectorPass.cpp b/src/Static/Transforms/MMDetectorPass.cpp similarity index 81% rename from src/MMDetectorPass.cpp rename to src/Static/Transforms/MMDetectorPass.cpp index c211842..1524d39 100644 --- a/src/MMDetectorPass.cpp +++ b/src/Static/Transforms/MMDetectorPass.cpp @@ -19,7 +19,7 @@ */ #include "MMDetectorPass.hpp" -#include "ModuleInfo.hpp" +#include "Static/ModuleInfo.hpp" #include "config.h" #include #include @@ -32,21 +32,19 @@ using namespace llvm; -void MMDetectorPass::setDeterminedMM(ModelType m) { PI->determinedMM = m; } - -bool isSCNAOrdering(AtomicOrdering o) +auto isSCNAOrdering(AtomicOrdering o) -> bool { return o == AtomicOrdering::SequentiallyConsistent || o == AtomicOrdering::NotAtomic; } -bool isRANAOrdering(AtomicOrdering o) +auto isRANAOrdering(AtomicOrdering o) -> bool { using AO = AtomicOrdering; return o == AO::Acquire || o == AO::Release || o == AO::AcquireRelease || o == AtomicOrdering::NotAtomic; } -bool MMDetectorPass::runOnModule(Module &M) +auto MMAnalysis::run(Module &M, ModuleAnalysisManager &MAM) -> MMAnalysis::Result { auto isSC = true; auto isRA = true; @@ -93,18 +91,12 @@ bool MMDetectorPass::runOnModule(Module &M) } } if (isSC) - setDeterminedMM(ModelType::SC); - if (isRA) - setDeterminedMM(ModelType::RA); - return false; + return {ModelType::SC}; + return isRA ? std::make_optional(ModelType::RA) : std::nullopt; } -ModulePass *createMMDetectorPass(PassModuleInfo *PI) +auto MMDetectorPass::run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses { - auto *p = new MMDetectorPass(); - p->setPassModuleInfo(PI); - return p; + PMI.determinedMM = MAM.getResult(M); + return PreservedAnalyses::all(); } - -char MMDetectorPass::ID = 42; -static RegisterPass P("sc-detector-casts", "Checks whether all accesses are SC."); diff --git a/src/MMDetectorPass.hpp b/src/Static/Transforms/MMDetectorPass.hpp similarity index 54% rename from src/MMDetectorPass.hpp rename to src/Static/Transforms/MMDetectorPass.hpp index cfd2528..a28768e 100644 --- a/src/MMDetectorPass.hpp +++ b/src/Static/Transforms/MMDetectorPass.hpp @@ -18,31 +18,40 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MM_DETECTOR_PASS_HPP__ -#define __MM_DETECTOR_PASS_HPP__ +#ifndef GENMC_MM_DETECTOR_PASS_HPP +#define GENMC_MM_DETECTOR_PASS_HPP -#include -#include -#include +#include + +#include + +using namespace llvm; class PassModuleInfo; enum class ModelType : std::uint8_t; -class MMDetectorPass : public llvm::ModulePass { - +class MMAnalysis : public AnalysisInfoMixin { public: - static char ID; + using Result = std::optional; + auto run(Module &M, ModuleAnalysisManager &AM) -> Result; - MMDetectorPass() : llvm::ModulePass(ID) {} + auto calculate(Module &M) -> Result; - void setPassModuleInfo(PassModuleInfo *I) { PI = I; } +private: + friend AnalysisInfoMixin; + static inline AnalysisKey Key; - virtual bool runOnModule(llvm::Module &M); + ModelType model{}; +}; + +class MMDetectorPass : public AnalysisInfoMixin { +public: + MMDetectorPass(PassModuleInfo &PMI) : PMI(PMI) {} -protected: - void setDeterminedMM(ModelType m); + auto run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses; - PassModuleInfo *PI = nullptr; +private: + PassModuleInfo &PMI; }; -#endif /* __MM_DETECTOR_PASS_HPP__ */ +#endif /* GENMC_MM_DETECTOR_PASS_HPP */ diff --git a/src/PromoteMemIntrinsicPass.cpp b/src/Static/Transforms/PromoteMemIntrinsicPass.cpp similarity index 82% rename from src/PromoteMemIntrinsicPass.cpp rename to src/Static/Transforms/PromoteMemIntrinsicPass.cpp index d6deb39..5de8a6c 100644 --- a/src/PromoteMemIntrinsicPass.cpp +++ b/src/Static/Transforms/PromoteMemIntrinsicPass.cpp @@ -19,8 +19,7 @@ */ #include "PromoteMemIntrinsicPass.hpp" -#include "Error.hpp" -#include "FunctionInlinerPass.hpp" +#include "Support/Error.hpp" #include #include #include @@ -33,31 +32,26 @@ #include #include -using namespace llvm; +#include -void PromoteMemIntrinsicPass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - /* Run after the inliner because it might generate new memcpys */ - // au.addRequired(); -} +using namespace llvm; -bool isPromotableMemIntrinsicOperand(Value *op) +auto isPromotableMemIntrinsicOperand(Value *op) -> bool { // Constant to capture MemSet too return isa(op) || isa(op) || isa(op); } -Type *getPromotionGEPType(Value *op) +auto getPromotionGEPType(Value *op) -> Type * { BUG_ON(!isPromotableMemIntrinsicOperand(op)); if (auto *v = dyn_cast(op)) return v->getValueType(); - else if (auto *ai = dyn_cast(op)) + if (auto *ai = dyn_cast(op)) return ai->getAllocatedType(); - else if (auto *gepi = dyn_cast(op)) + if (auto *gepi = dyn_cast(op)) return gepi->getResultElementType(); - else - BUG(); + BUG(); } void promoteMemCpy(IRBuilder<> &builder, Value *dst, Value *src, const std::vector &args, @@ -69,7 +63,6 @@ void promoteMemCpy(IRBuilder<> &builder, Value *dst, Value *src, const std::vect builder.CreateInBoundsGEP(getPromotionGEPType(dst), dst, args, "memcpy.dst.gep"); Value *srcLoad = builder.CreateLoad(typ, srcGEP, "memcpy.src.load"); Value *dstStore = builder.CreateStore(srcLoad, dstGEP); - return; } void promoteMemSet(IRBuilder<> &builder, Value *dst, Value *argVal, @@ -87,7 +80,6 @@ void promoteMemSet(IRBuilder<> &builder, Value *dst, Value *argVal, Value *dstGEP = builder.CreateInBoundsGEP(getPromotionGEPType(dst), dst, args, "memset.dst.gep"); Value *dstStore = builder.CreateStore(val, dstGEP); - return; } template @@ -124,7 +116,7 @@ void promoteMemIntrinsic(Type *typ, std::vector &args, F &&promoteFun) return; } -bool canPromoteMemIntrinsic(MemIntrinsic *MI) +auto canPromoteMemIntrinsic(MemIntrinsic *MI) -> bool { /* Skip if length is not a constant */ ConstantInt *length = dyn_cast(MI->getLength()); @@ -172,7 +164,7 @@ bool canPromoteMemIntrinsic(MemIntrinsic *MI) return true; } -bool PromoteMemIntrinsicPass::tryPromoteMemCpy(MemCpyInst *MI, Module &M) +auto tryPromoteMemCpy(MemCpyInst *MI, SmallVector &promoted) -> bool { if (!canPromoteMemIntrinsic(MI)) return false; @@ -195,7 +187,7 @@ bool PromoteMemIntrinsicPass::tryPromoteMemCpy(MemCpyInst *MI, Module &M) return true; } -bool PromoteMemIntrinsicPass::tryPromoteMemSet(MemSetInst *MS, Module &M) +auto tryPromoteMemSet(MemSetInst *MS, SmallVector &promoted) -> bool { if (!canPromoteMemIntrinsic(MS)) return false; @@ -218,9 +210,9 @@ bool PromoteMemIntrinsicPass::tryPromoteMemSet(MemSetInst *MS, Module &M) return true; } -void PromoteMemIntrinsicPass::removePromoted() +void removePromoted(std::ranges::input_range auto &&promoted) { - for (auto MI : promoted) { + for (auto *MI : promoted) { /* Are MI's operands used anywhere else? */ BitCastInst *dst = dyn_cast(MI->getRawDest()); @@ -234,35 +226,21 @@ void PromoteMemIntrinsicPass::removePromoted() if (src && src->hasNUses(0)) src->eraseFromParent(); } - - promoted.clear(); // fix canpromote functions that produce warnings } -bool PromoteMemIntrinsicPass::runOnModule(Module &M) +auto PromoteMemIntrinsicPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { - /* We assume that no new intrinsics are going to be generated */ - if (hasPromoted) - return false; - - bool modified = false; - /* Locate mem intrinsics of interest */ - for (auto &F : M) { - for (auto it = inst_iterator(F), ei = inst_end(F); it != ei; ++it) { - if (auto *MI = dyn_cast(&*it)) - modified |= tryPromoteMemCpy(MI, M); - if (auto *MS = dyn_cast(&*it)) - modified |= tryPromoteMemSet(MS, M); - } + SmallVector promoted; + auto modified = false; + for (auto &I : instructions(F)) { + if (auto *MI = dyn_cast(&I)) + modified |= tryPromoteMemCpy(MI, promoted); + if (auto *MS = dyn_cast(&I)) + modified |= tryPromoteMemSet(MS, promoted); } /* Erase promoted intrinsics from the code */ - removePromoted(); - hasPromoted = true; - - return modified; + removePromoted(promoted); + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -ModulePass *createPromoteMemIntrinsicPass() { return new PromoteMemIntrinsicPass(); } - -char PromoteMemIntrinsicPass::ID = 42; diff --git a/src/ConfirmationAnnotationPass.hpp b/src/Static/Transforms/PromoteMemIntrinsicPass.hpp similarity index 66% rename from src/ConfirmationAnnotationPass.hpp rename to src/Static/Transforms/PromoteMemIntrinsicPass.hpp index 3d9dc4a..6e43944 100644 --- a/src/ConfirmationAnnotationPass.hpp +++ b/src/Static/Transforms/PromoteMemIntrinsicPass.hpp @@ -18,24 +18,21 @@ * Author: Michalis Kokologiannakis */ -#ifndef __CONFIRMATION_ANNOTATION_PASS_HPP__ -#define __CONFIRMATION_ANNOTATION_PASS_HPP__ +#ifndef GENMC_PROMOTE_MEMINTRINSIC_PASS_HPP +#define GENMC_PROMOTE_MEMINTRINSIC_PASS_HPP +#include +#include +#include #include -using namespace llvm; +#include -class ConfirmationAnnotationPass : public FunctionPass { +using namespace llvm; +class PromoteMemIntrinsicPass : public PassInfoMixin { public: - ConfirmationAnnotationPass() : FunctionPass(ID){}; - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &F); - - static char ID; - -private: + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; }; -#endif /* __CONFIRMATION_ANNOTATION_PASS_HPP__ */ +#endif /* GENMC_PROMOTE_MEMINTRINSIC_PASS_HPP */ diff --git a/src/PropagateAssumesPass.cpp b/src/Static/Transforms/PropagateAssumesPass.cpp similarity index 80% rename from src/PropagateAssumesPass.cpp rename to src/Static/Transforms/PropagateAssumesPass.cpp index d87d68e..b6c1f78 100644 --- a/src/PropagateAssumesPass.cpp +++ b/src/Static/Transforms/PropagateAssumesPass.cpp @@ -19,10 +19,9 @@ */ #include "PropagateAssumesPass.hpp" -#include "Error.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" -#include "config.h" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Support/Error.hpp" #include #include @@ -36,9 +35,7 @@ using namespace llvm; -void PropagateAssumesPass::getAnalysisUsage(AnalysisUsage &au) const { au.setPreservesAll(); } - -bool isAssumeFalse(Instruction *i) +auto isAssumeFalse(Instruction *i) -> bool { auto *ci = dyn_cast(i); if (!ci || !isAssumeFunction(getCalledFunOrStripValName(*ci))) @@ -48,7 +45,7 @@ bool isAssumeFalse(Instruction *i) return arg && arg->isZero(); } -bool jumpsOnLoadResult(Value *cond) +auto jumpsOnLoadResult(Value *cond) -> bool { auto *sc = stripCastsConstOps(cond); if (isa(sc)) @@ -62,14 +59,14 @@ bool jumpsOnLoadResult(Value *cond) return false; } -Value *getOtherSuccCondition(BranchInst *bi, BasicBlock *succ) +auto getOtherSuccCondition(BranchInst *bi, BasicBlock *succ) -> Value * { if (bi->getSuccessor(1) == succ) return bi->getCondition(); return BinaryOperator::CreateNot(bi->getCondition(), "", bi); } -bool propagateAssumeToPred(CallInst *assume, BasicBlock *pred) +auto propagateAssumeToPred(CallInst *assume, BasicBlock *pred) -> bool { auto *bi = dyn_cast(pred->getTerminator()); if (!bi || bi->isUnconditional()) @@ -99,7 +96,7 @@ bool propagateAssumeToPred(CallInst *assume, BasicBlock *pred) return true; } -bool propagateAssume(CallInst *assume) +auto propagateAssume(CallInst *assume) -> bool { auto *bb = assume->getParent(); return std::accumulate(pred_begin(bb), pred_end(bb), false, @@ -108,22 +105,12 @@ bool propagateAssume(CallInst *assume) }); } -bool PropagateAssumesPass::runOnFunction(llvm::Function &F) +auto PropagateAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses { auto modified = false; for (auto &bb : F) if (isAssumeFalse(&*bb.begin())) modified |= propagateAssume(dyn_cast(&*bb.begin())); - return modified; + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -Pass *createPropagateAssumesPass() -{ - auto *p = new PropagateAssumesPass(); - return p; -} - -char PropagateAssumesPass::ID = 42; -static llvm::RegisterPass P("propagate-assumes", - "Propagates assume(0) upwards."); diff --git a/src/PropagateAssumesPass.hpp b/src/Static/Transforms/PropagateAssumesPass.hpp similarity index 67% rename from src/PropagateAssumesPass.hpp rename to src/Static/Transforms/PropagateAssumesPass.hpp index e1fd786..96e664b 100644 --- a/src/PropagateAssumesPass.hpp +++ b/src/Static/Transforms/PropagateAssumesPass.hpp @@ -18,21 +18,16 @@ * Author: Michalis Kokologiannakis */ -#ifndef __PROPAGATE_ASSUMES_PASS_HPP__ -#define __PROPAGATE_ASSUMES_PASS_HPP__ +#ifndef GENMC_PROPAGATE_ASSUMES_PASS_HPP +#define GENMC_PROPAGATE_ASSUMES_PASS_HPP -#include +#include -class PropagateAssumesPass : public llvm::FunctionPass { +using namespace llvm; +class PropagateAssumesPass : public PassInfoMixin { public: - static char ID; - - PropagateAssumesPass() : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &F) override; - - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; + auto run(Function &F, FunctionAnalysisManager &FAM) -> PreservedAnalyses; }; -#endif /* __PROPAGATE_ASSUMES_PASS_HPP__ */ +#endif /* GENMC_PROPAGATE_ASSUMES_PASS_HPP */ diff --git a/src/SpinAssumePass.cpp b/src/Static/Transforms/SpinAssumePass.cpp similarity index 81% rename from src/SpinAssumePass.cpp rename to src/Static/Transforms/SpinAssumePass.cpp index 5c131c6..e331cac 100644 --- a/src/SpinAssumePass.cpp +++ b/src/Static/Transforms/SpinAssumePass.cpp @@ -18,18 +18,17 @@ * Author: Michalis Kokologiannakis */ -#include "config.h" - -#include "CallInfoCollectionPass.hpp" -#include "DeclareInternalsPass.hpp" -#include "Error.hpp" -#include "EscapeCheckerPass.hpp" -#include "InstAnnotator.hpp" -#include "InterpreterEnumAPI.hpp" -#include "LLVMUtils.hpp" -#include "SExprVisitor.hpp" #include "SpinAssumePass.hpp" -#include "VSet.hpp" +#include "ADT/VSet.hpp" +#include "Runtime/InterpreterEnumAPI.hpp" +#include "Static/LLVMUtils.hpp" +#include "Static/Transforms/CallInfoCollectionPass.hpp" +#include "Static/Transforms/DeclareInternalsPass.hpp" +#include "Static/Transforms/EscapeCheckerPass.hpp" +#include "Static/Transforms/InstAnnotator.hpp" +#include "Support/Error.hpp" +#include "Support/SExprVisitor.hpp" +#include #include #include #include @@ -57,16 +56,6 @@ using namespace llvm; #define INSERT_PREHEADER_FOR_LOOP(L, DT, LI) llvm::InsertPreheaderForLoop(L, DT, LI, false) #endif -void SpinAssumePass::getAnalysisUsage(llvm::AnalysisUsage &au) const -{ - au.addRequired(); - au.addRequired(); - au.addRequired(); - au.addRequired(); - au.addRequired(); - au.setPreservesAll(); -} - void getLoopCASs(const Loop *l, SmallVector &cass) { for (auto bb = l->block_begin(); bb != l->block_end(); ++bb) { @@ -75,12 +64,11 @@ void getLoopCASs(const Loop *l, SmallVector &cass) cass.push_back(casi); } } - return; } -bool isBlockPHIClean(const BasicBlock *bb) { return !isa(&*bb->begin()); } +auto isBlockPHIClean(const BasicBlock *bb) -> bool { return !isa(&*bb->begin()); } -bool accessSameVariable(const Value *p1, const Value *p2) +auto accessSameVariable(const Value *p1, const Value *p2) -> bool { /* Check if they are trivially the same */ if (p1 == p2) @@ -337,7 +325,7 @@ bool tryGetCASResultExtracts(const std::vector &cass, * will return false.) */ bool failedCASesLeadToHeader(const std::vector &cass, BasicBlock *latch, - Loop *l, const CallInfoCollectionPass::CallSet &cleanSet) + Loop *l, const CallAnalysisResult::CallSet &cleanSet) { if (cass.empty()) return true; @@ -368,19 +356,25 @@ bool failedCASesLeadToHeader(const std::vector &cass, Basic return true; } -bool isStoreLocal(StoreInst *si, EscapeInfo &EI, DominatorTree &DT) +bool isStoreLocal(StoreInst *si, EscapeAnalysisResult &EAR, DominatorTree &DT) { /* A store is local if it is either marked or writes to dynamic memory */ auto attr = getWriteAttr(*si); - auto *alloc = EI.writesDynamicMemory(si->getPointerOperand()); - return (alloc && EI.escapesAfter(alloc, si, DT)) || !!(attr & WriteAttr::Local); + auto *alloc = EAR.writesDynamicMemory(si->getPointerOperand()); + return (alloc && EAR.escapesAfter(alloc, si, DT)) || !!(attr & WriteAttr::Local); } -bool SpinAssumePass::isPathToHeaderEffectFree(BasicBlock *latch, Loop *l, bool &checkDynamically) +bool isPathToHeaderEffectFree(BasicBlock *latch, Loop *l, ModuleAnalysisManager &MAM, + bool &checkDynamically) { - auto &cleanSet = getAnalysis().getCleanCalls(); - auto &EI = getAnalysis().getEscapeInfo(); - auto &DT = getAnalysis().getDomTree(); + auto &FAM = + MAM.getResult(*latch->getParent()->getParent()) + .getManager(); + auto &EAR = MAM.getResult(*latch->getParent()->getParent()); + auto &CAR = MAM.getResult(*latch->getParent()->getParent()); + auto &DT = FAM.getResult(*latch->getParent()); + auto &cleanSet = CAR.clean; + auto effects = false; std::vector cass; @@ -392,7 +386,7 @@ bool SpinAssumePass::isPathToHeaderEffectFree(BasicBlock *latch, Loop *l, bool & } /* Local stores are allowed */ if (auto *si = dyn_cast(&i)) { - if (isStoreLocal(si, EI, DT)) + if (isStoreLocal(si, EAR[latch->getParent()], DT)) return; } effects |= hasSideEffects(&i, &cleanSet); @@ -413,7 +407,8 @@ bool SpinAssumePass::isPathToHeaderEffectFree(BasicBlock *latch, Loop *l, bool & return casOK; } -template bool checkConstantsCondition(const Value *v1, const Value *v2, F &&cond) +template +auto checkConstantsCondition(const Value *v1, const Value *v2, F &&cond) -> bool { auto c1 = dyn_cast(v1); auto c2 = dyn_cast(v2); @@ -424,7 +419,7 @@ template bool checkConstantsCondition(const Value *v1, const Value return cond(c1->getValue(), c2->getValue()); } -bool areCancelingBinops(const AtomicRMWInst *a, const AtomicRMWInst *b) +auto areCancelingBinops(const AtomicRMWInst *a, const AtomicRMWInst *b) -> bool { using namespace llvm; using BinOp = AtomicRMWInst::BinOp; @@ -454,15 +449,23 @@ bool areCancelingBinops(const AtomicRMWInst *a, const AtomicRMWInst *b) return false; } -bool dominatesAndPostdominates(Instruction *a, Instruction *b, DominatorTree &DT, - PostDominatorTree &PDT) +auto dominatesAndPostdominates(Instruction *a, Instruction *b, DominatorTree &DT, + PostDominatorTree &PDT) -> bool { return DT.dominates(a, b) && PDT.dominates(a->getParent(), b->getParent()); } -bool SpinAssumePass::isPathToHeaderFAIZNE(BasicBlock *latch, Loop *l, Instruction *&lastEffect) +auto isPathToHeaderFAIZNE(BasicBlock *latch, Loop *l, ModuleAnalysisManager &MAM, + Instruction *&lastEffect) -> bool { - auto &cleanSet = getAnalysis().getCleanCalls(); + auto &FAM = + MAM.getResult(*latch->getParent()->getParent()) + .getManager(); + auto &CAR = MAM.getResult(*latch->getParent()->getParent()); + auto &DT = FAM.getResult(*latch->getParent()); + auto &PDT = FAM.getResult(*latch->getParent()); + auto &cleanSet = CAR.clean; + auto effects = false; VSet cass; VSet fais; @@ -484,8 +487,6 @@ bool SpinAssumePass::isPathToHeaderFAIZNE(BasicBlock *latch, Loop *l, Instructio return false; /* Check domination conditions; we need more checks here due to the (unordered) VSet */ - auto &DT = getAnalysis().getDomTree(); - auto &PDT = GET_POSTDOM_PASS(); AtomicRMWInst *inci = nullptr; AtomicRMWInst *deci = nullptr; @@ -511,9 +512,17 @@ bool SpinAssumePass::isPathToHeaderFAIZNE(BasicBlock *latch, Loop *l, Instructio return true; } -bool SpinAssumePass::isPathToHeaderLockZNE(BasicBlock *latch, Loop *l, Instruction *&lastEffect) +auto isPathToHeaderLockZNE(BasicBlock *latch, Loop *l, ModuleAnalysisManager &MAM, + Instruction *&lastEffect) -> bool { - auto &cleanSet = getAnalysis().getCleanCalls(); + auto &FAM = + MAM.getResult(*latch->getParent()->getParent()) + .getManager(); + auto &CAR = MAM.getResult(*latch->getParent()->getParent()); + auto &DT = FAM.getResult(*latch->getParent()); + auto &PDT = FAM.getResult(*latch->getParent()); + auto &cleanSet = CAR.clean; + auto effects = false; VSet locks; VSet unlocks; @@ -524,11 +533,11 @@ bool SpinAssumePass::isPathToHeaderLockZNE(BasicBlock *latch, Loop *l, Instructi auto name = getCalledFunOrStripValName(*ci); if (isInternalFunction(name)) { auto icode = internalFunNames.at(name); - if (icode == InternalFunctions::FN_MutexLock) { + if (icode == InternalFunctions::MutexLock) { locks.insert(ci); return; } - if (icode == InternalFunctions::FN_MutexUnlock) { + if (icode == InternalFunctions::MutexUnlock) { unlocks.insert(ci); return; } @@ -545,8 +554,6 @@ bool SpinAssumePass::isPathToHeaderLockZNE(BasicBlock *latch, Loop *l, Instructi if (effects || locks.size() != 1 || unlocks.size() != 1 || !phis.empty()) return false; - auto &DT = getAnalysis().getDomTree(); - auto &PDT = GET_POSTDOM_PASS(); auto lDomU = dominatesAndPostdominates(locks[0], unlocks[0], DT, PDT); if (!lDomU || !accessSameVariable(*locks[0]->arg_begin(), *unlocks[0]->arg_begin())) return false; @@ -555,7 +562,7 @@ bool SpinAssumePass::isPathToHeaderLockZNE(BasicBlock *latch, Loop *l, Instructi return true; } -Value *getOrCreateExitingCondition(BasicBlock *header, Instruction *term) +auto getOrCreateExitingCondition(BasicBlock *header, Instruction *term) -> Value * { if (auto *ibr = dyn_cast(term)) return ConstantInt::getFalse(term->getContext()); @@ -578,7 +585,6 @@ void addLoopBeginCallBeforeTerm(BasicBlock *preheader) auto *ci = CallInst::Create(beginFun, {}, "", term); ci->setMetadata("dbg", term->getMetadata("dbg")); - return; } void addSpinEndCallBeforeTerm(BasicBlock *latch, BasicBlock *header) @@ -590,7 +596,6 @@ void addSpinEndCallBeforeTerm(BasicBlock *latch, BasicBlock *header) auto *cond = getOrCreateExitingCondition(header, term); auto *ci = CallInst::Create(endFun, {cond}, "", term); ci->setMetadata("dbg", term->getMetadata("dbg")); - return; } void addPotentialSpinEndCallBeforeLastFai(BasicBlock *latch, BasicBlock *header, @@ -601,7 +606,6 @@ void addPotentialSpinEndCallBeforeLastFai(BasicBlock *latch, BasicBlock *header, auto *ci = CallInst::Create(endFun, {}, "", lastEffect); ci->setMetadata("dbg", lastEffect->getMetadata("dbg")); - return; } void addPotentialSpinEndCallBeforeUnlock(BasicBlock *latch, BasicBlock *header, @@ -612,7 +616,6 @@ void addPotentialSpinEndCallBeforeUnlock(BasicBlock *latch, BasicBlock *header, auto *ci = CallInst::Create(endFun, {}, "", lastEffect); ci->setMetadata("dbg", lastEffect->getMetadata("dbg")); - return; } void addSpinStartCall(Loop *l) @@ -624,7 +627,7 @@ void addSpinStartCall(Loop *l) auto *ci = CallInst::Create(startFun, {}, "", i); } -bool SpinAssumePass::runOnLoop(Loop *l, LPPassManager &lpm) +auto checkLoop(Loop *l, ModuleAnalysisManager &MAM, bool markStarts) -> bool { auto *header = l->getHeader(); @@ -639,17 +642,17 @@ bool SpinAssumePass::runOnLoop(Loop *l, LPPassManager &lpm) auto checkDynamically = false; llvm::Instruction *lastZNEEffect = nullptr; for (auto &latch : latches) { - if (isPathToHeaderFAIZNE(latch, l, lastZNEEffect)) { + if (isPathToHeaderFAIZNE(latch, l, MAM, lastZNEEffect)) { checkDynamically = true; modified = true; addPotentialSpinEndCallBeforeLastFai(latch, header, lastZNEEffect); - } else if (isPathToHeaderLockZNE(latch, l, lastZNEEffect)) { + } else if (isPathToHeaderLockZNE(latch, l, MAM, lastZNEEffect)) { /* Check for lockZNE before effect-free paths, * as locks are function calls too... */ checkDynamically = true; modified = true; addPotentialSpinEndCallBeforeUnlock(latch, header, lastZNEEffect); - } else if (isPathToHeaderEffectFree(latch, l, checkDynamically)) { + } else if (isPathToHeaderEffectFree(latch, l, MAM, checkDynamically)) { /* If we have to dynamically validate the loop, * the above check will return false, but the path * may be checked dynamically */ @@ -667,26 +670,30 @@ bool SpinAssumePass::runOnLoop(Loop *l, LPPassManager &lpm) addSpinStartCall(l); /* DSA also requires us to know when we actually enter the loop; * mark the beginning anyway to compose with liveness checks and nested loops */ - auto &DT = getAnalysis().getDomTree(); - auto &LI = lpm.getAnalysis().getLoopInfo(); + auto &FAM = MAM.getResult( + *header->getParent()->getParent()) + .getManager(); + auto &DT = FAM.getResult(*header->getParent()); + auto &LI = FAM.getResult(*header->getParent()); auto *ph = INSERT_PREHEADER_FOR_LOOP(l, &DT, &LI); addLoopBeginCallBeforeTerm(ph); } - /* If the transformation applied did not apply in all backedges, this is indeed a loop */ - if (!spinloop) - return modified; - /* An actual spinloop: we used to remove it from the loop list but let's keep it */ + /* Two cases: + * 1) If the transformation applied did not apply in all backedges, this is indeed a loop + * 2) An actual spinloop: we used to remove it from the loop list but let's keep it */ return modified; } -Pass *createSpinAssumePass(bool markStarts /* = false */) +auto SpinAssumePass::run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses { - auto *p = new SpinAssumePass(); - p->markSpinloopStarts(markStarts); - return p; + auto &FAM = MAM.getResult(M).getManager(); + auto modified = false; + for (auto &F : M | std::views::filter([&](auto &F) { return !F.isDeclaration(); })) { + auto &LI = FAM.getResult(F); + for (auto &L : std::views::reverse(LI.getLoopsInPreorder())) { + modified |= checkLoop(L, MAM, markStarts_); + } + } + return modified ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -char SpinAssumePass::ID = 42; -static llvm::RegisterPass P("spin-assume", - "Performs GenMC's spin-assume transformation."); diff --git a/src/EliminateCASPHIsPass.hpp b/src/Static/Transforms/SpinAssumePass.hpp similarity index 63% rename from src/EliminateCASPHIsPass.hpp rename to src/Static/Transforms/SpinAssumePass.hpp index 8a121f9..0552b83 100644 --- a/src/EliminateCASPHIsPass.hpp +++ b/src/Static/Transforms/SpinAssumePass.hpp @@ -18,21 +18,24 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ELIMINATE_CAS_PHIS_PASS_HPP__ -#define __ELIMINATE_CAS_PHIS_PASS_HPP__ +#ifndef GENMC_SPIN_ASSUME_PASS_HPP +#define GENMC_SPIN_ASSUME_PASS_HPP -#include +#include "ADT/VSet.hpp" -class EliminateCASPHIsPass : public llvm::FunctionPass { +#include -public: - static char ID; +using namespace llvm; - EliminateCASPHIsPass() : llvm::FunctionPass(ID) {} +class SpinAssumePass : public PassInfoMixin { +public: + SpinAssumePass(bool markStarts = false) : markStarts_(markStarts) {} - bool runOnFunction(llvm::Function &F) override; + auto run(Module &M, ModuleAnalysisManager &MAM) -> PreservedAnalyses; - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; +private: + /* Whether we should mark spinloop starts */ + bool markStarts_{}; }; -#endif /* __ELIMINATE_CAS_PHIS_PASS_HPP__ */ +#endif /* GENMC_SPIN_ASSUME_PASS_HPP */ diff --git a/src/ASize.cpp b/src/Support/ASize.cpp similarity index 100% rename from src/ASize.cpp rename to src/Support/ASize.cpp diff --git a/src/ASize.hpp b/src/Support/ASize.hpp similarity index 95% rename from src/ASize.hpp rename to src/Support/ASize.hpp index a0ef957..3813e13 100644 --- a/src/ASize.hpp +++ b/src/Support/ASize.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ASIZE_HPP__ -#define __ASIZE_HPP__ +#ifndef GENMC_ASIZE_HPP +#define GENMC_ASIZE_HPP #include "Error.hpp" #include "config.h" @@ -61,4 +61,4 @@ class ASize { Size size; }; -#endif /* __ASIZE_HPP__ */ +#endif /* GENMC_ASIZE_HPP */ diff --git a/src/Error.hpp b/src/Support/Error.hpp similarity index 98% rename from src/Error.hpp rename to src/Support/Error.hpp index ad575b8..173d404 100644 --- a/src/Error.hpp +++ b/src/Support/Error.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __ERROR_HPP__ -#define __ERROR_HPP__ +#ifndef GENMC_ERROR_HPP +#define GENMC_ERROR_HPP #include "Logger.hpp" #include @@ -119,4 +119,4 @@ template auto format(const std::pair &p) -> s return out.str(); } -#endif /* __ERROR_HPP__ */ +#endif /* GENMC_ERROR_HPP */ diff --git a/src/Logger.hpp b/src/Support/Logger.hpp similarity index 97% rename from src/Logger.hpp rename to src/Support/Logger.hpp index c96ed07..7b91c2d 100644 --- a/src/Logger.hpp +++ b/src/Support/Logger.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __LOGGER_HPP__ -#define __LOGGER_HPP__ +#ifndef GENMC_LOGGER_HPP +#define GENMC_LOGGER_HPP -#include "Verbosity.hpp" +#include "Config/Verbosity.hpp" #include #include @@ -125,4 +125,4 @@ inline VerbosityLevel logLevel = VerbosityLevel::Tip; else \ Logger(level) -#endif /* __LOGGER_HPP__ */ +#endif /* GENMC_LOGGER_HPP */ diff --git a/src/MemAccess.hpp b/src/Support/MemAccess.hpp similarity index 96% rename from src/MemAccess.hpp rename to src/Support/MemAccess.hpp index 83409b6..57ccd69 100644 --- a/src/MemAccess.hpp +++ b/src/Support/MemAccess.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __MEM_ACCESS_HPP__ -#define __MEM_ACCESS_HPP__ +#ifndef GENMC_MEM_ACCESS_HPP +#define GENMC_MEM_ACCESS_HPP #include "Error.hpp" #include "SAddr.hpp" @@ -81,4 +81,4 @@ class AAccess { AType type; }; -#endif /* __MEM_ACCESS_HPP__ */ +#endif /* GENMC_MEM_ACCESS_HPP */ diff --git a/src/NameInfo.cpp b/src/Support/NameInfo.cpp similarity index 100% rename from src/NameInfo.cpp rename to src/Support/NameInfo.cpp diff --git a/src/NameInfo.hpp b/src/Support/NameInfo.hpp similarity index 95% rename from src/NameInfo.hpp rename to src/Support/NameInfo.hpp index a43f0a1..b1ca11d 100644 --- a/src/NameInfo.hpp +++ b/src/Support/NameInfo.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __NAME_INFO_HPP__ -#define __NAME_INFO_HPP__ +#ifndef GENMC_NAME_INFO_HPP +#define GENMC_NAME_INFO_HPP #include "Error.hpp" #include "config.h" @@ -61,4 +61,4 @@ class NameInfo { OffsetInfo info; }; -#endif /* __NAME_INFO_HPP__ */ +#endif /* GENMC_NAME_INFO_HPP */ diff --git a/src/Parser.cpp b/src/Support/Parser.cpp similarity index 100% rename from src/Parser.cpp rename to src/Support/Parser.cpp diff --git a/src/Parser.hpp b/src/Support/Parser.hpp similarity index 94% rename from src/Parser.hpp rename to src/Support/Parser.hpp index c756d6a..ece56c5 100644 --- a/src/Parser.hpp +++ b/src/Support/Parser.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __PARSER_HPP__ -#define __PARSER_HPP__ +#ifndef GENMC_PARSER_HPP +#define GENMC_PARSER_HPP #include #include @@ -41,4 +41,4 @@ class Parser { llvm::raw_ostream &os = llvm::dbgs()); }; -#endif /* __PARSER_HPP__ */ +#endif /* GENMC_PARSER_HPP */ diff --git a/src/SAddr.cpp b/src/Support/SAddr.cpp similarity index 100% rename from src/SAddr.cpp rename to src/Support/SAddr.cpp diff --git a/src/SAddr.hpp b/src/Support/SAddr.hpp similarity index 98% rename from src/SAddr.hpp rename to src/Support/SAddr.hpp index 9087160..0ae0671 100644 --- a/src/SAddr.hpp +++ b/src/Support/SAddr.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __SADDR_HPP__ -#define __SADDR_HPP__ +#ifndef GENMC_SADDR_HPP +#define GENMC_SADDR_HPP #include "ASize.hpp" #include "Error.hpp" @@ -159,4 +159,4 @@ template <> struct hash { }; } // namespace std -#endif /* __SADDR_HPP__ */ +#endif /* GENMC_SADDR_HPP */ diff --git a/src/SAddrAllocator.hpp b/src/Support/SAddrAllocator.hpp similarity index 95% rename from src/SAddrAllocator.hpp rename to src/Support/SAddrAllocator.hpp index 375b064..45496a2 100644 --- a/src/SAddrAllocator.hpp +++ b/src/Support/SAddrAllocator.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __SADDR_ALLOCATOR_HPP__ -#define __SADDR_ALLOCATOR_HPP__ +#ifndef GENMC_SADDR_ALLOCATOR_HPP +#define GENMC_SADDR_ALLOCATOR_HPP #include "Error.hpp" #include "SAddr.hpp" @@ -76,4 +76,4 @@ class SAddrAllocator { SAddr::Width heapPool = 1; /* avoid allocating null */ }; -#endif /* __SADDR_ALLOCATOR_HPP__ */ +#endif /* GENMC_SADDR_ALLOCATOR_HPP */ diff --git a/src/SExpr.hpp b/src/Support/SExpr.hpp similarity index 99% rename from src/SExpr.hpp rename to src/Support/SExpr.hpp index 6e131ae..f3e5460 100644 --- a/src/SExpr.hpp +++ b/src/Support/SExpr.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __S_EXPR_HPP__ -#define __S_EXPR_HPP__ +#ifndef GENMC_S_EXPR_HPP +#define GENMC_S_EXPR_HPP #include "Error.hpp" #include "SVal.hpp" @@ -679,4 +679,4 @@ COMPARISON_EXPR_CLASS(Sge) #include "SExpr.tcc" -#endif /* __S_EXPR_HPP__ */ +#endif /* GENMC_S_EXPR_HPP */ diff --git a/src/SExpr.tcc b/src/Support/SExpr.tcc similarity index 100% rename from src/SExpr.tcc rename to src/Support/SExpr.tcc diff --git a/src/SExprVisitor.hpp b/src/Support/SExprVisitor.hpp similarity index 98% rename from src/SExprVisitor.hpp rename to src/Support/SExprVisitor.hpp index c30656f..d4161af 100644 --- a/src/SExprVisitor.hpp +++ b/src/Support/SExprVisitor.hpp @@ -18,14 +18,14 @@ * Author: Michalis Kokologiannakis */ -#ifndef __S_EXPR_VISITOR_HPP__ -#define __S_EXPR_VISITOR_HPP__ - -#include "Error.hpp" -#include "MemAccess.hpp" -#include "ModuleID.hpp" -#include "SExpr.hpp" -#include "VSet.hpp" +#ifndef GENMC_S_EXPR_VISITOR_HPP +#define GENMC_S_EXPR_VISITOR_HPP + +#include "ADT/VSet.hpp" +#include "Static/ModuleID.hpp" +#include "Support/Error.hpp" +#include "Support/MemAccess.hpp" +#include "Support/SExpr.hpp" #include #include @@ -490,4 +490,4 @@ class SExprTransformer #include "SExprVisitor.tcc" -#endif /* __S_EXPR_VISITOR_HPP__ */ +#endif /* GENMC_S_EXPR_VISITOR_HPP */ diff --git a/src/SExprVisitor.tcc b/src/Support/SExprVisitor.tcc similarity index 99% rename from src/SExprVisitor.tcc rename to src/Support/SExprVisitor.tcc index de3c06a..19f69af 100644 --- a/src/SExprVisitor.tcc +++ b/src/Support/SExprVisitor.tcc @@ -373,7 +373,7 @@ typename SExprEvaluator::RetTy SExprEvaluator::visitTruncExpr(TruncExpr template typename SExprEvaluator::RetTy SExprEvaluator::visitNotExpr(NotExpr &e) { - return !e.getKid(0); + return SVal(!e.getKid(0)); } #define IMPLEMENT_BINOP(op) \ diff --git a/src/SVal.cpp b/src/Support/SVal.cpp similarity index 100% rename from src/SVal.cpp rename to src/Support/SVal.cpp diff --git a/src/SVal.hpp b/src/Support/SVal.hpp similarity index 96% rename from src/SVal.hpp rename to src/Support/SVal.hpp index ddd3315..fc9f47c 100644 --- a/src/SVal.hpp +++ b/src/Support/SVal.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __SVAL_HPP__ -#define __SVAL_HPP__ +#ifndef GENMC_SVAL_HPP +#define GENMC_SVAL_HPP #include "Error.hpp" #include "config.h" @@ -42,7 +42,7 @@ class SVal { /* Constructors/destructors */ SVal() : value(0) {} - SVal(uint64_t v) : value(v) {} + explicit SVal(uint64_t v) : value(v) {} /* Returns a (limited) representation of this Value */ [[nodiscard]] auto get() const -> uint64_t { return value; } @@ -127,7 +127,7 @@ class SVal { IMPL_BINOP(<<); IMPL_BINOP(>>); - auto operator~() const -> SVal { return {~this->value}; } + auto operator~() const -> SVal { return SVal(~this->value); } explicit operator bool() const { return !!this->value; } @@ -159,4 +159,4 @@ struct SValUCmp { auto operator()(const SVal &lhs, const SVal &rhs) -> bool { return lhs.ult(rhs); } }; -#endif /* __SVAL_HPP__ */ +#endif /* GENMC_SVAL_HPP */ diff --git a/src/ThreadInfo.hpp b/src/Support/ThreadInfo.hpp similarity index 92% rename from src/ThreadInfo.hpp rename to src/Support/ThreadInfo.hpp index 0744b92..e746495 100644 --- a/src/ThreadInfo.hpp +++ b/src/Support/ThreadInfo.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __THREAD_INFO_HPP__ -#define __THREAD_INFO_HPP__ +#ifndef GENMC_THREAD_INFO_HPP +#define GENMC_THREAD_INFO_HPP #include "SVal.hpp" #include "config.h" @@ -37,4 +37,4 @@ struct ThreadInfo { {} }; -#endif /* __THREAD_INFO_HPP__ */ +#endif /* GENMC_THREAD_INFO_HPP */ diff --git a/src/ThreadPinner.cpp b/src/Support/ThreadPinner.cpp similarity index 100% rename from src/ThreadPinner.cpp rename to src/Support/ThreadPinner.cpp diff --git a/src/ThreadPinner.hpp b/src/Support/ThreadPinner.hpp similarity index 95% rename from src/ThreadPinner.hpp rename to src/Support/ThreadPinner.hpp index 4e44aa4..337d350 100644 --- a/src/ThreadPinner.hpp +++ b/src/Support/ThreadPinner.hpp @@ -18,8 +18,8 @@ * Author: Michalis Kokologiannakis */ -#ifndef __THREAD_PINNER_HPP__ -#define __THREAD_PINNER_HPP__ +#ifndef GENMC_THREAD_PINNER_HPP +#define GENMC_THREAD_PINNER_HPP #include "config.h" #include @@ -78,4 +78,4 @@ class ThreadPinner { #endif /* HAVE_LIBHWLOC */ -#endif /* __THREAD_PINNER_HPP__ */ +#endif /* GENMC_THREAD_PINNER_HPP */ diff --git a/src/ThreadPool.cpp b/src/Support/ThreadPool.cpp similarity index 100% rename from src/ThreadPool.cpp rename to src/Support/ThreadPool.cpp diff --git a/src/ThreadPool.hpp b/src/Support/ThreadPool.hpp similarity index 96% rename from src/ThreadPool.hpp rename to src/Support/ThreadPool.hpp index 7808ec3..5414fea 100644 --- a/src/ThreadPool.hpp +++ b/src/Support/ThreadPool.hpp @@ -18,14 +18,14 @@ * Author: Michalis Kokologiannakis */ -#ifndef __THREAD_POOL_HPP__ -#define __THREAD_POOL_HPP__ - -#include "DriverFactory.hpp" -#include "Error.hpp" -#include "ExecutionGraph.hpp" -#include "LLVMModule.hpp" -#include "ThreadPinner.hpp" +#ifndef GENMC_THREAD_POOL_HPP +#define GENMC_THREAD_POOL_HPP + +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "Static/LLVMModule.hpp" +#include "Support/Error.hpp" +#include "Support/ThreadPinner.hpp" +#include "Verification/DriverFactory.hpp" #include "config.h" #include #include @@ -246,4 +246,4 @@ class ThreadPool { ThreadJoiner joiner_; }; -#endif /* __THREAD_POOL_HPP__ */ +#endif /* GENMC_THREAD_POOL_HPP */ diff --git a/src/TSODriver.cpp b/src/TSODriver.cpp deleted file mode 100644 index e5f467d..0000000 --- a/src/TSODriver.cpp +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#include "TSODriver.hpp" -#include "ModuleInfo.hpp" - -TSODriver::TSODriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) - : GenMCDriver(conf, std::move(mod), std::move(MI), mode) -{} - -void TSODriver::visitCalc0_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc0_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_2(pLab, calcRes); - } - visitedCalc0_0[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitCalc0_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc0_0(pLab, calcRes); - } - visitedCalc0_1[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitCalc0_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(0)); - calcRes.updateIdx(lab->getPos()); - visitedCalc0_2[lab->getStamp().get()] = NodeStatus::left; -} - -View TSODriver::calculate0(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc0_0.clear(); - visitedCalc0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_1.clear(); - visitedCalc0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc0_2.clear(); - visitedCalc0_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc0_1(lab, calcRes); - return calcRes; -} -void TSODriver::visitCalc1_0(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - if (auto pLab = tc_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = tj_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - if (auto pLab = rf_pred(g, lab); pLab) { - auto status = visitedCalc1_2[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_2(pLab, calcRes); - } - visitedCalc1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitCalc1_1(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto status = visitedCalc1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitCalc1_0(pLab, calcRes); - } - visitedCalc1_1[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitCalc1_2(const EventLabel *lab, View &calcRes) -{ - auto &g = getGraph(); - - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::entered; - calcRes.update(lab->view(1)); - calcRes.updateIdx(lab->getPos()); - visitedCalc1_2[lab->getStamp().get()] = NodeStatus::left; -} - -View TSODriver::calculate1(const EventLabel *lab) -{ - auto &g = getGraph(); - View calcRes; - - calcRes.updateIdx(lab->getPos().prev()); - visitedCalc1_0.clear(); - visitedCalc1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_1.clear(); - visitedCalc1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedCalc1_2.clear(); - visitedCalc1_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - - visitCalc1_1(lab, calcRes); - return calcRes; -} -std::vector> TSODriver::calculateSaved(const EventLabel *lab) -{ - return std::move(saved); -} - -std::vector TSODriver::calculateViews(const EventLabel *lab) -{ - views.push_back(calculate0(lab)); - views.push_back(calculate1(lab)); - return std::move(views); -} - -void TSODriver::updateMMViews(EventLabel *lab) -{ - lab->setCalculated(calculateSaved(lab)); - lab->setViews(calculateViews(lab)); - lab->setPrefixView(calculatePrefixView(lab)); -} - -bool TSODriver::isDepTracking() const { return 0; } - -bool TSODriver::visitInclusionLHS0_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab0 = lab; - return false; - } - visitedInclusionLHS0_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS0_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS0_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS0_0(pLab, v)) - return false; - } - visitedInclusionLHS0_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::checkInclusion0(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS0_0.clear(); - visitedInclusionLHS0_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS0_1.clear(); - visitedInclusionLHS0_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS0_1(lab, v); -} - -void TSODriver::visitInclusionLHS1_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept1[lab->getStamp().get()] = true; - visitedInclusionLHS1_0[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitInclusionLHS1_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - !llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS1_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS1_0(pLab); - } - visitedInclusionLHS1_1[lab->getStamp().get()] = NodeStatus::left; -} - -bool TSODriver::checkInclusion1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS1_0.clear(); - visitedInclusionLHS1_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS1_1.clear(); - visitedInclusionLHS1_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept1.clear(); - lhsAccept1.resize(g.getMaxStamp().get() + 1, false); - rhsAccept1.clear(); - rhsAccept1.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS1_1(lab); - for (auto i = 0u; i < lhsAccept1.size(); i++) { - if (lhsAccept1[i] && !rhsAccept1[i]) { - racyLab1 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool TSODriver::visitInclusionLHS2_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab2 = lab; - return false; - } - visitedInclusionLHS2_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS2_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - visitedInclusionLHS2_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS2_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab) && !llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS2_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS2_1(pLab, v)) - return false; - } - visitedInclusionLHS2_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::checkInclusion2(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS2_0.clear(); - visitedInclusionLHS2_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_1.clear(); - visitedInclusionLHS2_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS2_2.clear(); - visitedInclusionLHS2_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS2_2(lab, v); -} - -void TSODriver::visitInclusionLHS3_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept3[lab->getStamp().get()] = true; - visitedInclusionLHS3_0[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitInclusionLHS3_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { - auto status = visitedInclusionLHS3_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_0(pLab); - } - visitedInclusionLHS3_1[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitInclusionLHS3_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS3_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS3_1(pLab); - } - visitedInclusionLHS3_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool TSODriver::checkInclusion3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS3_0.clear(); - visitedInclusionLHS3_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_1.clear(); - visitedInclusionLHS3_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS3_2.clear(); - visitedInclusionLHS3_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept3.clear(); - lhsAccept3.resize(g.getMaxStamp().get() + 1, false); - rhsAccept3.clear(); - rhsAccept3.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS3_2(lab); - for (auto i = 0u; i < lhsAccept3.size(); i++) { - if (lhsAccept3[i] && !rhsAccept3[i]) { - racyLab3 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool TSODriver::visitInclusionLHS4_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab4 = lab; - return false; - } - visitedInclusionLHS4_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS4_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::entered; - for (auto &tmp : alloc_succs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - visitedInclusionLHS4_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS4_2(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - llvm::dyn_cast(pLab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(pLab))) { - auto status = visitedInclusionLHS4_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = free_pred(g, lab); pLab) { - auto status = visitedInclusionLHS4_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && !visitInclusionLHS4_1(pLab, v)) - return false; - } - visitedInclusionLHS4_2[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::checkInclusion4(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS4_0.clear(); - visitedInclusionLHS4_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_1.clear(); - visitedInclusionLHS4_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS4_2.clear(); - visitedInclusionLHS4_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS4_2(lab, v); -} - -void TSODriver::visitInclusionLHS5_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::entered; - lhsAccept5[lab->getStamp().get()] = true; - visitedInclusionLHS5_0[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitInclusionLHS5_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::entered; - if (auto pLab = free_succ(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto status = visitedInclusionLHS5_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_0(pLab); - } - visitedInclusionLHS5_1[lab->getStamp().get()] = NodeStatus::left; -} - -void TSODriver::visitInclusionLHS5_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab) && - llvm::dyn_cast(lab)->getAddr().isDynamic() && - !isHazptrProtected(llvm::dyn_cast(lab))) - if (auto pLab = alloc_pred(g, lab); pLab) { - auto status = visitedInclusionLHS5_1[pLab->getStamp().get()]; - if (status == NodeStatus::unseen) - visitInclusionLHS5_1(pLab); - } - visitedInclusionLHS5_2[lab->getStamp().get()] = NodeStatus::left; -} - -bool TSODriver::checkInclusion5(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedInclusionLHS5_0.clear(); - visitedInclusionLHS5_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_1.clear(); - visitedInclusionLHS5_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS5_2.clear(); - visitedInclusionLHS5_2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - lhsAccept5.clear(); - lhsAccept5.resize(g.getMaxStamp().get() + 1, false); - rhsAccept5.clear(); - rhsAccept5.resize(g.getMaxStamp().get() + 1, false); - - visitInclusionLHS5_2(lab); - for (auto i = 0u; i < lhsAccept5.size(); i++) { - if (lhsAccept5[i] && !rhsAccept5[i]) { - racyLab5 = &*std::find_if(label_begin(g), label_end(g), - [&](auto &lab) { return lab.getStamp() == i; }); - return false; - } - } - return true; -} - -bool TSODriver::visitInclusionLHS6_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab6 = lab; - return false; - } - visitedInclusionLHS6_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS6_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && lab->isNotAtomic() && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS6_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS6_0(pLab, v)) - return false; - } - visitedInclusionLHS6_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::checkInclusion6(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(0); - - visitedInclusionLHS6_0.clear(); - visitedInclusionLHS6_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS6_1.clear(); - visitedInclusionLHS6_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS6_1(lab, v); -} - -bool TSODriver::visitInclusionLHS7_0(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::entered; - if (!v.contains(lab->getPos())) { - racyLab7 = lab; - return false; - } - visitedInclusionLHS7_0[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::visitInclusionLHS7_1(const EventLabel *lab, const View &v) const -{ - auto &g = getGraph(); - - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::entered; - if (true && llvm::isa(lab)) - for (auto &tmp : samelocs(g, lab)) - if (auto *pLab = &tmp; true) - if (true && llvm::isa(pLab)) { - auto status = - visitedInclusionLHS7_0[pLab->getStamp().get()]; - if (status == NodeStatus::unseen && - !visitInclusionLHS7_0(pLab, v)) - return false; - } - visitedInclusionLHS7_1[lab->getStamp().get()] = NodeStatus::left; - return true; -} - -bool TSODriver::checkInclusion7(const EventLabel *lab) const -{ - auto &g = getGraph(); - auto &v = lab->view(1); - - visitedInclusionLHS7_0.clear(); - visitedInclusionLHS7_0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - visitedInclusionLHS7_1.clear(); - visitedInclusionLHS7_1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); - return true && visitInclusionLHS7_1(lab, v); -} - -VerificationError TSODriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const -{ - if (!checkInclusion0(lab)) { - race = racyLab0; - return VerificationError::VE_AccessNonMalloc; - } - - if (!checkInclusion1(lab)) { - race = racyLab1; - return VerificationError::VE_DoubleFree; - } - - if (!checkInclusion2(lab)) { - race = racyLab2; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion3(lab)) { - race = racyLab3; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion4(lab)) { - race = racyLab4; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion5(lab)) { - race = racyLab5; - return VerificationError::VE_AccessFreed; - } - - if (!checkInclusion6(lab)) { - race = racyLab6; - return VerificationError::VE_RaceNotAtomic; - } - - return VerificationError::VE_OK; -} - -std::vector -TSODriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const -{ - std::vector result; - - if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkInclusion7(lab)) { - racyLabs.push_back(racyLab7); - result.push_back(VerificationError::VE_WWRace); - } - - return result; -} - -bool TSODriver::visitAcyclic0_0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_0[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool TSODriver::visitAcyclic0_1(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_1[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool TSODriver::visitAcyclic0_2(const EventLabel *lab) const -{ - auto &g = getGraph(); - - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - visitedAcyclic0_2[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool TSODriver::visitAcyclic0_3(const EventLabel *lab) const -{ - auto &g = getGraph(); - - ++visitedAccepting0; - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::entered}; - if (auto pLab = co_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - for (auto &tmp : fr_imm_preds(g, lab)) - if (auto *pLab = &tmp; true) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = rfe_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab) && - ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || - (llvm::isa(pLab) && g.isRMWStore(pLab)))) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) - if (true && pLab->isSC() && llvm::isa(pLab)) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_3[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_3(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_0[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_0(pLab)) - return false; - else if (node.status == NodeStatus::entered && visitedAccepting0 > node.count) - return false; - } - if (true && lab->isSC() && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_2[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_2(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - if (true && llvm::isa(lab)) - if (auto pLab = po_imm_pred(g, lab); pLab) { - auto &node = visitedAcyclic0_1[pLab->getStamp().get()]; - if (node.status == NodeStatus::unseen && !visitAcyclic0_1(pLab)) - return false; - else if (node.status == NodeStatus::entered && - visitedAccepting0 > node.count) - return false; - } - --visitedAccepting0; - visitedAcyclic0_3[lab->getStamp().get()] = {visitedAccepting0, NodeStatus::left}; - return true; -} - -bool TSODriver::isAcyclic0(const EventLabel *lab) const -{ - auto &g = getGraph(); - - if (!shouldVisitAcyclic0()) - return true; - - visitedAccepting0 = 0; - visitedAcyclic0_0.clear(); - visitedAcyclic0_0.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_1.clear(); - visitedAcyclic0_1.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_2.clear(); - visitedAcyclic0_2.resize(g.getMaxStamp().get() + 1); - visitedAcyclic0_3.clear(); - visitedAcyclic0_3.resize(g.getMaxStamp().get() + 1); - return true && visitAcyclic0_3(lab); -} - -bool TSODriver::isConsistent(const EventLabel *lab) const { return true && isAcyclic0(lab); } - -bool TSODriver::isRecAcyclic(const EventLabel *lab) const -{ - visitedRecAccepting = 0; - return true; -} - -bool TSODriver::isRecoveryValid(const EventLabel *lab) const { return isRecAcyclic(lab); } - -View TSODriver::calcPPoRfBefore(const EventLabel *lab) const -{ - auto &g = getGraph(); - View pporf; - pporf.updateIdx(lab->getPos()); - - auto *pLab = g.getPreviousLabel(lab); - if (!pLab) - return pporf; - pporf.update(pLab->getPrefixView()); - if (auto *rLab = llvm::dyn_cast(pLab)) - pporf.update(rLab->getRf()->getPrefixView()); - if (auto *tsLab = llvm::dyn_cast(pLab)) - pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); - if (auto *tjLab = llvm::dyn_cast(pLab)) - pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); - return pporf; -} -std::unique_ptr TSODriver::calculatePrefixView(const EventLabel *lab) const -{ - return std::make_unique(calcPPoRfBefore(lab)); -} - -const View &TSODriver::getHbView(const EventLabel *lab) const { return lab->view(0); } - -bool TSODriver::isWriteRfBefore(Event a, Event b) -{ - auto &g = getGraph(); - auto &before = g.getEventLabel(b)->view(0); - if (before.contains(a)) - return true; - - const EventLabel *lab = g.getEventLabel(a); - - BUG_ON(!llvm::isa(lab)); - auto *wLab = static_cast(lab); - for (auto &rLab : wLab->readers()) - if (before.contains(rLab.getPos())) - return true; - return false; -} - -std::vector TSODriver::getInitRfsAtLoc(SAddr addr) -{ - std::vector result; - - for (const auto &lab : labels(getGraph())) { - if (auto *rLab = llvm::dyn_cast(&lab)) - if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) - result.push_back(rLab->getPos()); - } - return result; -} - -bool TSODriver::isHbOptRfBefore(const Event e, const Event write) -{ - auto &g = getGraph(); - const EventLabel *lab = g.getEventLabel(write); - - BUG_ON(!llvm::isa(lab)); - auto *sLab = static_cast(lab); - if (sLab->view(0).contains(e)) - return true; - - for (auto &rLab : sLab->readers()) { - if (rLab.view(0).contains(e)) - return true; - } - return false; -} - -ExecutionGraph::co_iterator TSODriver::splitLocMOBefore(SAddr addr, Event e) -{ - auto &g = getGraph(); - auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), - [&](auto &lab) { return isWriteRfBefore(lab.getPos(), e); }); - /* Convert to forward iterator, but be _really_ careful */ - if (rit == g.co_rend(addr)) - return g.co_begin(addr); - return ++ExecutionGraph::co_iterator(*rit); -} - -ExecutionGraph::co_iterator TSODriver::splitLocMOAfterHb(SAddr addr, const Event read) -{ - auto &g = getGraph(); - - auto initRfs = g.getInitRfsAtLoc(addr); - if (std::any_of(initRfs.begin(), initRfs.end(), [&read, &g](const Event &rf) { - return g.getEventLabel(rf)->view(0).contains(read); - })) - return g.co_begin(addr); - - auto it = std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(read, lab.getPos()); }); - if (it == g.co_end(addr) || it->view(0).contains(read)) - return it; - return ++it; -} - -ExecutionGraph::co_iterator TSODriver::splitLocMOAfter(SAddr addr, const Event e) -{ - auto &g = getGraph(); - return std::find_if(g.co_begin(addr), g.co_end(addr), - [&](auto &lab) { return isHbOptRfBefore(e, lab.getPos()); }); -} - -std::vector TSODriver::getCoherentStores(SAddr addr, Event read) -{ - auto &g = getGraph(); - std::vector stores; - - /* - * If there are no stores (rf?;hb)-before the current event - * then we can read read from all concurrent stores and the - * initializer store. Otherwise, we can read from all concurrent - * stores and the mo-latest of the (rf?;hb)-before stores. - */ - auto begIt = splitLocMOBefore(addr, read); - if (begIt == g.co_begin(addr)) - stores.push_back(Event::getInit()); - else { - stores.push_back((--begIt)->getPos()); - ++begIt; - } - - /* - * If the model supports out-of-order execution we have to also - * account for the possibility the read is hb-before some other - * store, or some read that reads from a store. - */ - auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); - std::transform(begIt, endIt, std::back_inserter(stores), - [&](auto &lab) { return lab.getPos(); }); - return stores; -} - -std::vector TSODriver::getMOOptRfAfter(const WriteLabel *sLab) -{ - std::vector after; - std::vector rfAfter; - - const auto &g = getGraph(); - std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - return after; -} - -std::vector TSODriver::getMOInvOptRfAfter(const WriteLabel *sLab) -{ - auto &g = getGraph(); - std::vector after; - std::vector rfAfter; - - /* First, add (mo;rf?)-before */ - std::for_each(g.co_pred_begin(sLab), g.co_pred_end(sLab), [&](auto &wLab) { - after.push_back(wLab.getPos()); - std::transform(wLab.readers_begin(), wLab.readers_end(), - std::back_inserter(rfAfter), [&](auto &rLab) { return &rLab; }); - }); - std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), - [](auto *rLab) { return rLab->getPos(); }); - - /* Then, we add the reader list for the initializer */ - auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); - after.insert(after.end(), initRfs.begin(), initRfs.end()); - return after; -} - -std::vector TSODriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) -{ - auto &g = getGraph(); - auto ls = g.getRevisitable(sLab, pporf); - - /* If this store is po- and mo-maximal then we are done */ - if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) - return ls; - - /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ - auto optRfs = getMOOptRfAfter(sLab); - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - const View &before = g.getEventLabel(e)->view(0); - return std::any_of( - optRfs.begin(), optRfs.end(), - [&](Event ev) { return before.contains(ev); }); - }), - ls.end()); - - /* If out-of-order event addition is not supported, then we are done - * due to po-maximality */ - if (!isDepTracking()) - return ls; - - /* Otherwise, we also have to exclude hb-before loads */ - ls.erase(std::remove_if(ls.begin(), ls.end(), - [&](Event e) { - return g.getEventLabel(sLab->getPos())->view(0).contains(e); - }), - ls.end()); - - /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in - * the resulting graph */ - auto &before = pporf; - auto moInvOptRfs = getMOInvOptRfAfter(sLab); - ls.erase(std::remove_if( - ls.begin(), ls.end(), - [&](Event e) { - auto *eLab = g.getEventLabel(e); - auto v = g.getViewFromStamp(eLab->getStamp()); - v->update(before); - return std::any_of( - moInvOptRfs.begin(), moInvOptRfs.end(), [&](Event ev) { - return v->contains(ev) && - g.getEventLabel(ev)->view(0).contains(e); - }); - }), - ls.end()); - - return ls; -} - -llvm::iterator_range -TSODriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) -{ - auto &g = getGraph(); - - /* If it is an RMW store, there is only one possible position in MO */ - if (isRMW) { - if (auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev()))) { - auto *rfLab = rLab->getRf(); - BUG_ON(!rfLab); - if (auto *wLab = llvm::dyn_cast(rfLab)) { - auto wIt = g.co_succ_begin(wLab); - return llvm::iterator_range(wIt, wIt); - } - return llvm::iterator_range(g.co_begin(addr), - g.co_begin(addr)); - } - BUG(); - } - - /* Otherwise, we calculate the full range and add the store */ - auto rangeBegin = splitLocMOBefore(addr, store); - auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); - return llvm::iterator_range(rangeBegin, rangeEnd); -} diff --git a/src/TSODriver.hpp b/src/TSODriver.hpp deleted file mode 100644 index d802782..0000000 --- a/src/TSODriver.hpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * GenMC -- Generic Model Checking. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-3.0.html. - * - * Author: Michalis Kokologiannakis - */ - -/******************************************************************************* - * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. - *******************************************************************************/ - -#ifndef __TSO_DRIVER_HPP__ -#define __TSO_DRIVER_HPP__ - -#include "ExecutionGraph.hpp" -#include "GenMCDriver.hpp" -#include "GraphIterators.hpp" -#include "MaximalIterator.hpp" -#include "VSet.hpp" -#include "VerificationError.hpp" -#include "config.h" -#include -#include - -class TSODriver : public GenMCDriver { - -private: - enum class NodeStatus : unsigned char { unseen, entered, left }; - - struct NodeCountStatus { - NodeCountStatus() = default; - NodeCountStatus(uint16_t c, NodeStatus s) : count(c), status(s) {} - uint16_t count = 0; - NodeStatus status = NodeStatus::unseen; - }; - -public: - TSODriver(std::shared_ptr conf, std::unique_ptr mod, - std::unique_ptr MI, - GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); - - std::vector> calculateSaved(const EventLabel *lab); - std::vector calculateViews(const EventLabel *lab); - void updateMMViews(EventLabel *lab) override; - bool isDepTracking() const override; - bool isConsistent(const EventLabel *lab) const override; - VerificationError checkErrors(const EventLabel *lab, - const EventLabel *&race) const override; - std::vector - checkWarnings(const EventLabel *lab, const VSet &seenWarnings, - std::vector &racyLabs) const; - bool isRecoveryValid(const EventLabel *lab) const override; - std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; - const View &getHbView(const EventLabel *lab) const override; - std::vector getCoherentStores(SAddr addr, Event read) override; - std::vector getCoherentRevisits(const WriteLabel *sLab, - const VectorClock &pporf) override; - llvm::iterator_range - getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; - -private: - bool isWriteRfBefore(Event a, Event b); - std::vector getInitRfsAtLoc(SAddr addr); - bool isHbOptRfBefore(const Event e, const Event write); - ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); - ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); - ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); - std::vector getMOOptRfAfter(const WriteLabel *sLab); - std::vector getMOInvOptRfAfter(const WriteLabel *sLab); - - void visitCalc0_0(const EventLabel *lab, View &calcRes); - void visitCalc0_1(const EventLabel *lab, View &calcRes); - void visitCalc0_2(const EventLabel *lab, View &calcRes); - - View calculate0(const EventLabel *lab); - - mutable std::vector visitedCalc0_0; - mutable std::vector visitedCalc0_1; - mutable std::vector visitedCalc0_2; - - void visitCalc1_0(const EventLabel *lab, View &calcRes); - void visitCalc1_1(const EventLabel *lab, View &calcRes); - void visitCalc1_2(const EventLabel *lab, View &calcRes); - - View calculate1(const EventLabel *lab); - - mutable std::vector visitedCalc1_0; - mutable std::vector visitedCalc1_1; - mutable std::vector visitedCalc1_2; - - bool visitInclusionLHS0_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS0_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion0(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS0_0; - mutable std::vector visitedInclusionLHS0_1; - mutable std::vector visitedInclusionRHS0_0; - mutable std::vector visitedInclusionRHS0_1; - - mutable std::vector lhsAccept0; - mutable std::vector rhsAccept0; - - mutable const EventLabel *racyLab0 = nullptr; - - void visitInclusionLHS1_0(const EventLabel *lab) const; - void visitInclusionLHS1_1(const EventLabel *lab) const; - - bool checkInclusion1(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS1_0; - mutable std::vector visitedInclusionLHS1_1; - - mutable std::vector lhsAccept1; - mutable std::vector rhsAccept1; - - mutable const EventLabel *racyLab1 = nullptr; - - bool visitInclusionLHS2_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS2_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion2(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS2_0; - mutable std::vector visitedInclusionLHS2_1; - mutable std::vector visitedInclusionLHS2_2; - mutable std::vector visitedInclusionRHS2_0; - mutable std::vector visitedInclusionRHS2_1; - - mutable std::vector lhsAccept2; - mutable std::vector rhsAccept2; - - mutable const EventLabel *racyLab2 = nullptr; - - void visitInclusionLHS3_0(const EventLabel *lab) const; - void visitInclusionLHS3_1(const EventLabel *lab) const; - void visitInclusionLHS3_2(const EventLabel *lab) const; - - bool checkInclusion3(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS3_0; - mutable std::vector visitedInclusionLHS3_1; - mutable std::vector visitedInclusionLHS3_2; - - mutable std::vector lhsAccept3; - mutable std::vector rhsAccept3; - - mutable const EventLabel *racyLab3 = nullptr; - - bool visitInclusionLHS4_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_1(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS4_2(const EventLabel *lab, const View &v) const; - - bool checkInclusion4(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS4_0; - mutable std::vector visitedInclusionLHS4_1; - mutable std::vector visitedInclusionLHS4_2; - mutable std::vector visitedInclusionRHS4_0; - mutable std::vector visitedInclusionRHS4_1; - - mutable std::vector lhsAccept4; - mutable std::vector rhsAccept4; - - mutable const EventLabel *racyLab4 = nullptr; - - void visitInclusionLHS5_0(const EventLabel *lab) const; - void visitInclusionLHS5_1(const EventLabel *lab) const; - void visitInclusionLHS5_2(const EventLabel *lab) const; - - bool checkInclusion5(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS5_0; - mutable std::vector visitedInclusionLHS5_1; - mutable std::vector visitedInclusionLHS5_2; - - mutable std::vector lhsAccept5; - mutable std::vector rhsAccept5; - - mutable const EventLabel *racyLab5 = nullptr; - - bool visitInclusionLHS6_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS6_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion6(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS6_0; - mutable std::vector visitedInclusionLHS6_1; - mutable std::vector visitedInclusionRHS6_0; - mutable std::vector visitedInclusionRHS6_1; - - mutable std::vector lhsAccept6; - mutable std::vector rhsAccept6; - - mutable const EventLabel *racyLab6 = nullptr; - - bool visitInclusionLHS7_0(const EventLabel *lab, const View &v) const; - bool visitInclusionLHS7_1(const EventLabel *lab, const View &v) const; - - bool checkInclusion7(const EventLabel *lab) const; - - mutable std::vector visitedInclusionLHS7_0; - mutable std::vector visitedInclusionLHS7_1; - mutable std::vector visitedInclusionRHS7_0; - mutable std::vector visitedInclusionRHS7_1; - - mutable std::vector lhsAccept7; - mutable std::vector rhsAccept7; - - mutable const EventLabel *racyLab7 = nullptr; - - bool visitAcyclic0_0(const EventLabel *lab) const; - bool visitAcyclic0_1(const EventLabel *lab) const; - bool visitAcyclic0_2(const EventLabel *lab) const; - bool visitAcyclic0_3(const EventLabel *lab) const; - - bool isAcyclic0(const EventLabel *lab) const; - - mutable std::vector visitedAcyclic0_0; - mutable std::vector visitedAcyclic0_1; - mutable std::vector visitedAcyclic0_2; - mutable std::vector visitedAcyclic0_3; - - mutable uint16_t visitedAccepting0 = 0; - bool shouldVisitAcyclic0(void) const { return true; }; - - bool isRecAcyclic(const EventLabel *lab) const; - - mutable uint16_t visitedRecAccepting = 0; - void visitPPoRf0(const EventLabel *lab, View &pporf) const; - - View calcPPoRfBefore(const EventLabel *lab) const; - - mutable std::vector visitedPPoRf0; - - mutable std::vector> saved; - mutable std::vector views; -}; - -#endif /* __TSO_DRIVER_HPP__ */ diff --git a/src/BoundDecider.cpp b/src/Verification/Consistency/BoundDecider.cpp similarity index 91% rename from src/BoundDecider.cpp rename to src/Verification/Consistency/BoundDecider.cpp index 65584a2..57456f1 100644 --- a/src/BoundDecider.cpp +++ b/src/Verification/Consistency/BoundDecider.cpp @@ -19,9 +19,9 @@ */ #include "BoundDecider.hpp" -#include "Config.hpp" -#include "ContextBoundDecider.hpp" -#include "RoundBoundDecider.hpp" +#include "Config/Config.hpp" +#include "Verification/Consistency/ContextBoundDecider.hpp" +#include "Verification/Consistency/RoundBoundDecider.hpp" auto BoundDecider::doesExecutionExceedBound(const ExecutionGraph &g, unsigned int bound, BoundCalculationStrategy strategy) -> bool diff --git a/src/BoundDecider.hpp b/src/Verification/Consistency/BoundDecider.hpp similarity index 95% rename from src/BoundDecider.hpp rename to src/Verification/Consistency/BoundDecider.hpp index 2f10590..f8f2ce6 100644 --- a/src/BoundDecider.hpp +++ b/src/Verification/Consistency/BoundDecider.hpp @@ -18,8 +18,8 @@ * Author: Iason Marmanis */ -#ifndef __BOUND_DECIDER_HPP__ -#define __BOUND_DECIDER_HPP__ +#ifndef GENMC_BOUND_DECIDER_HPP +#define GENMC_BOUND_DECIDER_HPP #include @@ -63,4 +63,4 @@ class BoundDecider { const ExecutionGraph *graph = nullptr; }; -#endif /* __BOUND_DECIDER_HPP__ */ +#endif /* GENMC_BOUND_DECIDER_HPP */ diff --git a/src/ContextBoundDecider.cpp b/src/Verification/Consistency/ContextBoundDecider.cpp similarity index 96% rename from src/ContextBoundDecider.cpp rename to src/Verification/Consistency/ContextBoundDecider.cpp index 49be964..86ec67e 100644 --- a/src/ContextBoundDecider.cpp +++ b/src/Verification/Consistency/ContextBoundDecider.cpp @@ -19,15 +19,15 @@ */ #include "ContextBoundDecider.hpp" -#include "ExecutionGraph.hpp" -#include "GraphIterators.hpp" -#include "View.hpp" +#include "ADT/View.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" #include auto canBlock(const ExecutionGraph &g, const View &s, int t) -> bool { - const auto *nLab = g.getNextLabel(Event(t, s.getMax(t))); + const auto *nLab = g.getNextLabel(g.getEventLabel(Event(t, s.getMax(t)))); return nLab && (llvm::isa(nLab) || llvm::isa(nLab) || llvm::isa(nLab)); } @@ -36,12 +36,12 @@ auto isEnabled(const ExecutionGraph &g, const View &v, int t) -> bool { auto last = Event(t, v.getMax(t)); const auto *llab = g.getEventLabel(last); - if (llab->isTerminator()) + if (llvm::isa(llab)) return false; /* If thread has no more events in the current execution, * we consider it disabled for the context-bound. */ - const auto *nLab = g.getNextLabel(last); + const auto *nLab = g.getNextLabel(llab); if (!nLab) return false; diff --git a/src/ContextBoundDecider.hpp b/src/Verification/Consistency/ContextBoundDecider.hpp similarity index 89% rename from src/ContextBoundDecider.hpp rename to src/Verification/Consistency/ContextBoundDecider.hpp index cfaaaaa..a538599 100644 --- a/src/ContextBoundDecider.hpp +++ b/src/Verification/Consistency/ContextBoundDecider.hpp @@ -18,11 +18,11 @@ * Author: Iason Marmanis */ -#ifndef __CONTEXT_BOUND_DECIDER_HPP__ -#define __CONTEXT_BOUND_DECIDER_HPP__ +#ifndef GENMC_CONTEXT_BOUND_DECIDER_HPP +#define GENMC_CONTEXT_BOUND_DECIDER_HPP +#include "ADT/View.hpp" #include "BoundDecider.hpp" -#include "View.hpp" class ContextBoundDecider : public BoundDecider { @@ -39,4 +39,4 @@ class ContextBoundDecider : public BoundDecider { #endif }; -#endif /* __CONTEXT_BOUND_DECIDER_HPP__ */ +#endif /* GENMC_CONTEXT_BOUND_DECIDER_HPP */ diff --git a/src/Verification/Consistency/IMMDriver.cpp b/src/Verification/Consistency/IMMDriver.cpp new file mode 100644 index 0000000..13f78f6 --- /dev/null +++ b/src/Verification/Consistency/IMMDriver.cpp @@ -0,0 +1,5439 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#include "IMMDriver.hpp" +#include "Static/ModuleInfo.hpp" + +IMMDriver::IMMDriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) + : GenMCDriver(conf, std::move(mod), std::move(MI), mode) {} + +bool IMMDriver::isDepTracking() const +{ + return 1; +} + +bool IMMDriver::visitCalc61_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool IMMDriver::visitCalc61_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitCalc61_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_2[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_2[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + + visitedCalc61_2[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool IMMDriver::visitCalc61_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_3[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_3[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + + visitedCalc61_3[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool IMMDriver::visitCalc61_4(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_4[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_4[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc61_4[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool IMMDriver::visitCalc61_5(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_5[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_5[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + + visitedCalc61_5[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool IMMDriver::visitCalc61_6(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto status = visitedCalc61_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc61_7(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitCalc61_7(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View IMMDriver::visitCalc61(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + visitedCalc61_2.clear(); + visitedCalc61_2.resize(g.getMaxStamp().get() + 1); + visitedCalc61_3.clear(); + visitedCalc61_3.resize(g.getMaxStamp().get() + 1); + visitedCalc61_4.clear(); + visitedCalc61_4.resize(g.getMaxStamp().get() + 1); + visitedCalc61_5.clear(); + visitedCalc61_5.resize(g.getMaxStamp().get() + 1); + + visitCalc61_6(lab, calcRes); + return calcRes; +} +auto IMMDriver::checkCalc61(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc61(lab); +} +bool IMMDriver::visitCalc73_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool IMMDriver::visitCalc73_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(1)); true) { + if (!visitCalc73_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitCalc73_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc73_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc73_3(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc73_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitCalc73_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc73_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc73_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc73_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc73_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc73_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc73_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View IMMDriver::visitCalc73(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc73_2(lab, calcRes); + return calcRes; +} +auto IMMDriver::checkCalc73(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc73(lab); +} +void IMMDriver::calculateSaved(EventLabel *lab) +{ +} + +void IMMDriver::calculateViews(EventLabel *lab) +{ + lab->addView(checkCalc61(lab)); + lab->addView(checkCalc73(lab)); +} + +void IMMDriver::updateMMViews(EventLabel *lab) +{ + calculateViews(lab); + calculateSaved(lab); +} + +const View &IMMDriver::getHbView(const EventLabel *lab) const +{ + return lab->view(0); +} + + +bool IMMDriver::isWriteRfBefore(Event a, Event b) +{ + auto &g = getGraph(); + auto &before = g.getEventLabel(b)->view(0); + if (before.contains(a)) + return true; + + const EventLabel *lab = g.getEventLabel(a); + + BUG_ON(!llvm::isa(lab)); + auto *wLab = static_cast(lab); + for (auto &rLab : wLab->readers()) + if (before.contains(rLab.getPos())) + return true; + return false; +} + +std::vector +IMMDriver::getInitRfsAtLoc(SAddr addr) +{ + std::vector result; + + for (const auto &lab : getGraph().labels()) { + if (auto *rLab = llvm::dyn_cast(&lab)) + if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) + result.push_back(rLab->getPos()); + } + return result; +} + +bool IMMDriver::isHbOptRfBefore(const Event e, const Event write) +{ + auto &g = getGraph(); + const EventLabel *lab = g.getEventLabel(write); + + BUG_ON(!llvm::isa(lab)); + auto *sLab = static_cast(lab); + if (sLab->view(0).contains(e)) + return true; + + for (auto &rLab : sLab->readers()) { + if (rLab.view(0).contains(e)) + return true; + } + return false; +} + +ExecutionGraph::co_iterator +IMMDriver::splitLocMOBefore(SAddr addr, Event e) +{ + auto &g = getGraph(); + auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), [&](auto &lab){ + return isWriteRfBefore(lab.getPos(), e); + }); + /* Convert to forward iterator, but be _really_ careful */ + if (rit == g.co_rend(addr)) + return g.co_begin(addr); + return ++ExecutionGraph::co_iterator(*rit); +} + +ExecutionGraph::co_iterator +IMMDriver::splitLocMOAfterHb(SAddr addr, const Event read) +{ + auto &g = getGraph(); + + auto initRfs = g.getInitRfsAtLoc(addr); + if (std::any_of(initRfs.begin(), initRfs.end(), [&read,&g](const Event &rf){ + return g.getEventLabel(rf)->view(0).contains(read); + })) + return g.co_begin(addr); + + auto it = std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(read, lab.getPos()); + }); + if (it == g.co_end(addr) || it->view(0).contains(read)) + return it; + return ++it; +} + +ExecutionGraph::co_iterator +IMMDriver::splitLocMOAfter(SAddr addr, const Event e) +{ + auto &g = getGraph(); + return std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(e, lab.getPos()); + }); +} + +std::vector +IMMDriver::getCoherentStores(SAddr addr, Event read) +{ + auto &g = getGraph(); + std::vector stores; + + /* Fastpath: co_max(G) is po-before R */ + auto comax = g.co_rbegin(addr) == g.co_rend(addr) ? Event::getInit() : + g.co_rbegin(addr)->getPos(); + if (comax.thread == read.thread && comax.index < read.index) + return {comax}; + + /* + * If there are no stores (rf?;hb)-before the current event + * then we can read read from all concurrent stores and the + * initializer store. Otherwise, we can read from all concurrent + * stores and the mo-latest of the (rf?;hb)-before stores. + */ + auto begIt = splitLocMOBefore(addr, read); + if (begIt == g.co_begin(addr)) + stores.push_back(Event::getInit()); + else { + stores.push_back((--begIt)->getPos()); + ++begIt; + } + + /* + * If the model supports out-of-order execution we have to also + * account for the possibility the read is hb-before some other + * store, or some read that reads from a store. + */ + auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); + std::transform(begIt, endIt, std::back_inserter(stores), [&](auto &lab){ + return lab.getPos(); + }); + return stores; +} + +std::vector +IMMDriver::getMOOptRfAfter(const WriteLabel *sLab) +{ + std::vector after; + std::vector rfAfter; + + const auto &g = getGraph(); + std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), + [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + return after; +} + +std::vector +IMMDriver::getMOInvOptRfAfter(const WriteLabel *sLab) +{ + auto &g = getGraph(); + std::vector after; + std::vector rfAfter; + + /* First, add (mo;rf?)-before */ + std::for_each(g.co_pred_begin(sLab), + g.co_pred_end(sLab), [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + + /* Then, we add the reader list for the initializer */ + auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); + after.insert(after.end(), initRfs.begin(), initRfs.end()); + return after; +} + +static std::vector +getRevisitableFrom(const ExecutionGraph &g, const WriteLabel *sLab, + const VectorClock &pporf, const WriteLabel *coPred) +{ + auto pendingRMW = g.getPendingRMW(sLab); + std::vector loads; + + for (auto &rLab : coPred->readers()) { + if (!pporf.contains(rLab.getPos()) && rLab.getAddr() == sLab->getAddr() && + rLab.isRevisitable() && rLab.wasAddedMax()) + loads.push_back(rLab.getPos()); + } + if (!pendingRMW.isInitializer()) + loads.erase(std::remove_if(loads.begin(), loads.end(), + [&](Event &e) { + auto *confLab = g.getEventLabel(pendingRMW); + return g.getEventLabel(e)->getStamp() > + confLab->getStamp(); + }), + loads.end()); + return loads; +} + +std::vector +IMMDriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) +{ + auto &g = getGraph(); + std::vector ls; + + /* Fastpath: previous co-max is ppo-before SLAB */ + auto prevCoMaxIt = std::find_if(g.co_rbegin(sLab->getAddr()), g.co_rend(sLab->getAddr()), + [&](auto &lab) { return lab.getPos() != sLab->getPos(); }); + if (prevCoMaxIt != g.co_rend(sLab->getAddr()) && pporf.contains(prevCoMaxIt->getPos())) { + ls = getRevisitableFrom(g, sLab, pporf, &*prevCoMaxIt); + } else { + ls = g.getRevisitable(sLab, pporf); + } + + /* If this store is po- and mo-maximal then we are done */ + if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) + return ls; + + /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ + auto optRfs = getMOOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { const View &before = g.getEventLabel(e)->view(0); + return std::any_of(optRfs.begin(), optRfs.end(), + [&](Event ev) + { return before.contains(ev); }); + }), ls.end()); + + /* If out-of-order event addition is not supported, then we are done + * due to po-maximality */ + if (!isDepTracking()) + return ls; + + /* Otherwise, we also have to exclude hb-before loads */ + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { return g.getEventLabel(sLab->getPos())->view(0).contains(e); }), + ls.end()); + + /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in + * the resulting graph */ + auto &before = pporf; + auto moInvOptRfs = getMOInvOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { auto *eLab = g.getEventLabel(e); + auto v = g.getViewFromStamp(eLab->getStamp()); + v->update(before); + return std::any_of(moInvOptRfs.begin(), + moInvOptRfs.end(), + [&](Event ev) + { return v->contains(ev) && + g.getEventLabel(ev)->view(0).contains(e); }); + }), + ls.end()); + + return ls; +} + +std::vector +IMMDriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) +{ + auto &g = getGraph(); + std::vector result; + + /* If it is an RMW store, there is only one possible position in MO */ + if (isRMW) { + auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev())); + BUG_ON(!rLab); + auto *rfLab = rLab->getRf(); + BUG_ON(!rfLab); + result.push_back(rfLab->getPos()); + return result; + } + + /* Otherwise, we calculate the full range and add the store */ + auto rangeBegin = splitLocMOBefore(addr, store); + auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); + auto cos = llvm::iterator_range(rangeBegin, rangeEnd) | + std::views::filter([&](auto &sLab) { return !g.isRMWStore(sLab.getPos()); }) | + std::views::transform([&](auto &sLab) { + auto *pLab = g.co_imm_pred(&sLab); + return pLab ? pLab->getPos() : Event::getInit(); + }); + std::ranges::copy(cos, std::back_inserter(result)); + result.push_back(rangeEnd == g.co_end(addr) ? g.co_max(addr)->getPos() + : !g.co_imm_pred(&*rangeEnd) ? Event::getInit() + : g.co_imm_pred(&*rangeEnd)->getPos()); + return result; +} +bool IMMDriver::visitCoherence_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedCoherenceAccepting; + + + --visitedCoherenceAccepting; + return true; +} + +bool IMMDriver::visitCoherence_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_6(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitCoherence_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitCoherence_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitCoherence_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitCoherence_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitCoherence_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + return true; +} + +bool IMMDriver::visitCoherenceFull() const +{ + auto &g = getGraph(); + + visitedCoherenceAccepting = 0; + visitedCoherence_1.clear(); + visitedCoherence_1.resize(g.getMaxStamp().get() + 1); + visitedCoherence_2.clear(); + visitedCoherence_2.resize(g.getMaxStamp().get() + 1); + visitedCoherence_3.clear(); + visitedCoherence_3.resize(g.getMaxStamp().get() + 1); + visitedCoherence_4.clear(); + visitedCoherence_4.resize(g.getMaxStamp().get() + 1); + visitedCoherence_5.clear(); + visitedCoherence_5.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedCoherence_1[lab.getStamp().get()].status != NodeStatus::unseen || visitCoherence_1(&lab); }); +} + +bool IMMDriver::visitConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic1_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_4[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_4[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic1_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_6[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitConsAcyclic1_5(pLab)){ + return false; + } + } + visitedConsAcyclic1_6[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_7[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_7[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_8[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_8[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_9[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_9[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_10(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_10[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic1_11(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_10[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_11(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic1_12(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_12[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_12[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_13(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_13[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_13[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_14(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_14[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_14[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_15(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_15[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_15[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_16(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_16[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic1_17(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_16[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_17(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic1_18(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_18[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_18[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_19(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_19[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_19[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_20(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_20[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_20[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1_21(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedConsAcyclic1Accepting; + visitedConsAcyclic1_21[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + --visitedConsAcyclic1Accepting; + visitedConsAcyclic1_21[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_4.clear(); + visitedConsAcyclic1_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_6.clear(); + visitedConsAcyclic1_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_7.clear(); + visitedConsAcyclic1_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_8.clear(); + visitedConsAcyclic1_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_9.clear(); + visitedConsAcyclic1_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_10.clear(); + visitedConsAcyclic1_10.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_12.clear(); + visitedConsAcyclic1_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_13.clear(); + visitedConsAcyclic1_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_14.clear(); + visitedConsAcyclic1_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_15.clear(); + visitedConsAcyclic1_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_16.clear(); + visitedConsAcyclic1_16.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_18.clear(); + visitedConsAcyclic1_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_19.clear(); + visitedConsAcyclic1_19.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_20.clear(); + visitedConsAcyclic1_20.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_21.clear(); + visitedConsAcyclic1_21.resize(g.getMaxStamp().get() + 1); + return true + && (visitedConsAcyclic1_6[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_6(lab)) + && (visitedConsAcyclic1_7[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_7(lab)) + && (visitedConsAcyclic1_8[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_8(lab)) + && (visitedConsAcyclic1_10[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_10(lab)) + && (visitedConsAcyclic1_13[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_13(lab)) + && (visitedConsAcyclic1_14[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_14(lab)) + && (visitedConsAcyclic1_20[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_20(lab)) + && (visitedConsAcyclic1_21[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_21(lab)); +} + +bool IMMDriver::visitConsAcyclic1Full() const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_4.clear(); + visitedConsAcyclic1_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_6.clear(); + visitedConsAcyclic1_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_7.clear(); + visitedConsAcyclic1_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_8.clear(); + visitedConsAcyclic1_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_9.clear(); + visitedConsAcyclic1_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_10.clear(); + visitedConsAcyclic1_10.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_12.clear(); + visitedConsAcyclic1_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_13.clear(); + visitedConsAcyclic1_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_14.clear(); + visitedConsAcyclic1_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_15.clear(); + visitedConsAcyclic1_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_16.clear(); + visitedConsAcyclic1_16.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_18.clear(); + visitedConsAcyclic1_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_19.clear(); + visitedConsAcyclic1_19.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_20.clear(); + visitedConsAcyclic1_20.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_21.clear(); + visitedConsAcyclic1_21.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedConsAcyclic1_21[lab.getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_21(&lab); }); +} + +bool IMMDriver::visitLHSUnlessConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool IMMDriver::visitLHSUnlessConsAcyclic1_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + for (auto &tmp : other_labels(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + if (!visitLHSUnlessConsAcyclic1_0(pLab)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitUnlessConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessConsAcyclic1Accepting.clear(); + visitedLHSUnlessConsAcyclic1Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessConsAcyclic1Accepting.clear(); + visitedRHSUnlessConsAcyclic1Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessConsAcyclic1_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessConsAcyclic1Accepting.size(); i++) { + if (visitedLHSUnlessConsAcyclic1Accepting[i] && !visitedRHSUnlessConsAcyclic1Accepting[i]) { + return false; + } + } + return true; +} + +bool IMMDriver::checkConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessConsAcyclic1(lab)) + return true; + + return visitConsAcyclic1(lab); +} +bool IMMDriver::visitConsAcyclic2_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_0[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_0[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_1[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_1[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_2[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rfi_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic2_3(pLab)){ + return false; + } + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rfi_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rfi_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_2[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic2_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_4[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_4[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_5[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = poloc_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_5[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_6[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_6[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_7[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_11[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_11(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_11[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_11(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_7[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_8[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_11[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_11(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_8[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_9[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic2_10(pLab)){ + return false; + } + } + visitedConsAcyclic2_9[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_10(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic2_11(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_11[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_11[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_11(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_11[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_12(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_12[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic2_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : fr_imm_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic2_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_12[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_13(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_13[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_13[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_14(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_14[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_14[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_15(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_15[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + if (!visitConsAcyclic2_16(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_15[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_16(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool IMMDriver::visitConsAcyclic2_17(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_17[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_17[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_18(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2_18[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic2_18[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2_19(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedConsAcyclic2Accepting; + visitedConsAcyclic2_19[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::entered }; + + + if (auto pLab = rfe_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : detour_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedConsAcyclic2_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic2_17[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_17(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedConsAcyclic2_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab) { + auto &node = visitedConsAcyclic2_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic2_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic2Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + --visitedConsAcyclic2Accepting; + visitedConsAcyclic2_19[lab->getStamp().get()] = { visitedConsAcyclic2Accepting, NodeStatus::left }; + return true; +} + +bool IMMDriver::visitConsAcyclic2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic2Accepting = 0; + visitedConsAcyclic2_0.clear(); + visitedConsAcyclic2_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_1.clear(); + visitedConsAcyclic2_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_2.clear(); + visitedConsAcyclic2_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_4.clear(); + visitedConsAcyclic2_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_5.clear(); + visitedConsAcyclic2_5.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_6.clear(); + visitedConsAcyclic2_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_7.clear(); + visitedConsAcyclic2_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_8.clear(); + visitedConsAcyclic2_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_9.clear(); + visitedConsAcyclic2_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_11.clear(); + visitedConsAcyclic2_11.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_12.clear(); + visitedConsAcyclic2_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_13.clear(); + visitedConsAcyclic2_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_14.clear(); + visitedConsAcyclic2_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_15.clear(); + visitedConsAcyclic2_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_17.clear(); + visitedConsAcyclic2_17.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_18.clear(); + visitedConsAcyclic2_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_19.clear(); + visitedConsAcyclic2_19.resize(g.getMaxStamp().get() + 1); + return true + && (visitedConsAcyclic2_6[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_6(lab)) + && (visitedConsAcyclic2_7[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_7(lab)) + && (visitedConsAcyclic2_9[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_9(lab)) + && (visitedConsAcyclic2_12[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_12(lab)) + && (visitedConsAcyclic2_13[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_13(lab)); +} + +bool IMMDriver::visitConsAcyclic2Full() const +{ + auto &g = getGraph(); + + visitedConsAcyclic2Accepting = 0; + visitedConsAcyclic2_0.clear(); + visitedConsAcyclic2_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_1.clear(); + visitedConsAcyclic2_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_2.clear(); + visitedConsAcyclic2_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_4.clear(); + visitedConsAcyclic2_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_5.clear(); + visitedConsAcyclic2_5.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_6.clear(); + visitedConsAcyclic2_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_7.clear(); + visitedConsAcyclic2_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_8.clear(); + visitedConsAcyclic2_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_9.clear(); + visitedConsAcyclic2_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_11.clear(); + visitedConsAcyclic2_11.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_12.clear(); + visitedConsAcyclic2_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_13.clear(); + visitedConsAcyclic2_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_14.clear(); + visitedConsAcyclic2_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_15.clear(); + visitedConsAcyclic2_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_17.clear(); + visitedConsAcyclic2_17.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_18.clear(); + visitedConsAcyclic2_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic2_19.clear(); + visitedConsAcyclic2_19.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedConsAcyclic2_19[lab.getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic2_19(&lab); }); +} + +bool IMMDriver::checkConsAcyclic2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return visitConsAcyclic2(lab); +} +bool IMMDriver::visitWarning3(const EventLabel *lab) const +{ + return false; +} + +bool IMMDriver::visitLHSUnlessWarning3_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool IMMDriver::visitLHSUnlessWarning3_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessWarning3_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool IMMDriver::visitUnlessWarning3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessWarning3Accepting.clear(); + visitedLHSUnlessWarning3Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessWarning3_1(lab, v); +} + +bool IMMDriver::checkWarning3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessWarning3(lab)) + return true; + + return visitWarning3(lab); +} +VerificationError IMMDriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const +{ + return VerificationError::VE_OK; +} + +std::vector IMMDriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const +{ + std::vector result; + + if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkWarning3(lab)) { + racyLabs.push_back(cexLab); + result.push_back(VerificationError::VE_WWRace); + } + + return result; +} + +bool IMMDriver::isConsistent(const EventLabel *lab) const +{ + + return true + && checkConsAcyclic1(lab) + && checkConsAcyclic2(lab); +} + +void IMMDriver::visitPPoRf0(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf0[lab->getStamp().get()] = NodeStatus::entered; + pporf.updateIdx(lab->getPos()); + visitedPPoRf0[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf1(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf1[lab->getStamp().get()] = NodeStatus::entered; + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab))if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf1[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf2(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf2[lab->getStamp().get()] = NodeStatus::entered; + pporf.updateIdx(lab->getPos()); + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf2(pLab, pporf); + } + visitedPPoRf2[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf3(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf3[lab->getStamp().get()] = NodeStatus::entered; + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf4(pLab, pporf); + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = rfe_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + for (auto &tmp : detour_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && lab->isAtLeastRelease())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (auto pLab = tc_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = tj_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = rfe_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + for (auto &tmp : detour_preds(g, lab)) if (auto *pLab = &tmp; true)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (true && lab->isAtLeastRelease())if (auto pLab = po_imm_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf2(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab)if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf2(pLab, pporf); + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (auto pLab = rfe_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab))for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + for (auto &tmp : detour_preds(g, lab)) if (auto *pLab = &tmp; true) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && lab->isAtLeastRelease())if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf3[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf4(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf4[lab->getStamp().get()] = NodeStatus::entered; + if (auto pLab = poloc_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf4(pLab, pporf); + } + if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = poloc_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf4[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf5(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf5[lab->getStamp().get()] = NodeStatus::entered; + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab))) && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf5[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf6(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf6[lab->getStamp().get()] = NodeStatus::entered; + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + if (auto pLab = rfi_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedPPoRf5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf5(pLab, pporf); + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + if (auto pLab = rfi_pred(g, lab); pLab) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (auto pLab = rfi_pred(g, lab); pLab) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + for (auto &p : ctrl_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + for (auto &p : data_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf6[lab->getStamp().get()] = NodeStatus::left; +} + +void IMMDriver::visitPPoRf7(const EventLabel *lab, DepView &pporf) const +{ + auto &g = getGraph(); + + visitedPPoRf7[lab->getStamp().get()] = NodeStatus::entered; + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf3(pLab, pporf); + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf6[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf6(pLab, pporf); + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedPPoRf7[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf7(pLab, pporf); + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable())if (pporf.updateIdx(pLab->getPos()); true) { + auto status = visitedPPoRf0[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf0(pLab, pporf); + } + for (auto &p : addr_preds(g, lab)) if (auto *pLab = g.getEventLabel(p); true)if (true && pLab->isDependable()) { + auto status = visitedPPoRf1[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) + visitPPoRf1(pLab, pporf); + } + visitedPPoRf7[lab->getStamp().get()] = NodeStatus::left; +} + +DepView IMMDriver::calcPPoRfBefore(const EventLabel *lab) const +{ + auto &g = getGraph(); + DepView pporf; + pporf.updateIdx(lab->getPos()); + visitedPPoRf0.clear(); + visitedPPoRf0.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf1.clear(); + visitedPPoRf1.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf2.clear(); + visitedPPoRf2.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf3.clear(); + visitedPPoRf3.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf4.clear(); + visitedPPoRf4.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf5.clear(); + visitedPPoRf5.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf6.clear(); + visitedPPoRf6.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + visitedPPoRf7.clear(); + visitedPPoRf7.resize(g.getMaxStamp().get() + 1, NodeStatus::unseen); + + visitPPoRf1(lab, pporf); + visitPPoRf3(lab, pporf); + return pporf; +} +std::unique_ptr IMMDriver::calculatePrefixView(const EventLabel *lab) const +{ + return std::make_unique(calcPPoRfBefore(lab)); +} diff --git a/src/Verification/Consistency/IMMDriver.hpp b/src/Verification/Consistency/IMMDriver.hpp new file mode 100644 index 0000000..386f38f --- /dev/null +++ b/src/Verification/Consistency/IMMDriver.hpp @@ -0,0 +1,279 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#ifndef GENMC_IMM_DRIVER_HPP +#define GENMC_IMM_DRIVER_HPP + +#include "config.h" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Verification/GenMCDriver.hpp" +#include "Verification/VerificationError.hpp" +#include +#include + +class IMMDriver : public GenMCDriver { + +private: + enum class NodeStatus : unsigned char { unseen, entered, left }; + + struct NodeVisitStatus { + NodeVisitStatus() = default; + NodeVisitStatus(uint32_t c, NodeStatus s) : count(c), status(s) {} + uint32_t count{}; + NodeStatus status{}; + }; + +public: + IMMDriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); + + void calculateSaved(EventLabel *lab); + void calculateViews(EventLabel *lab); + void updateMMViews(EventLabel *lab) override; + bool isDepTracking() const override; + bool isConsistent(const EventLabel *lab) const override; + VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const override; + std::vector checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const; + std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; + const View &getHbView(const EventLabel *lab) const override; + std::vector getCoherentStores(SAddr addr, Event read) override; + std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) override; + std::vector getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; + +private: + bool isWriteRfBefore(Event a, Event b); + std::vector getInitRfsAtLoc(SAddr addr); + bool isHbOptRfBefore(const Event e, const Event write); + ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); + ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); + ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); + std::vector getMOOptRfAfter(const WriteLabel *sLab); + std::vector getMOInvOptRfAfter(const WriteLabel *sLab); + mutable const EventLabel *cexLab{}; + + mutable std::vector visitedCalc61_0; + mutable std::vector visitedCalc61_1; + mutable std::vector visitedCalc61_2; + mutable std::vector visitedCalc61_3; + mutable std::vector visitedCalc61_4; + mutable std::vector visitedCalc61_5; + mutable std::vector visitedCalc61_6; + mutable std::vector visitedCalc61_7; + + bool visitCalc61_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_3(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_4(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_5(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_6(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_7(const EventLabel *lab, View &calcRes) const; + + View visitCalc61(const EventLabel *lab) const; + const View&getHbStableView(const EventLabel *lab) const { return lab->view(0); } + + auto checkCalc61(const EventLabel *lab) const; + mutable std::vector visitedCalc73_0; + mutable std::vector visitedCalc73_1; + mutable std::vector visitedCalc73_2; + mutable std::vector visitedCalc73_3; + + bool visitCalc73_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc73_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc73_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc73_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc73(const EventLabel *lab) const; + const View&getPorfStableView(const EventLabel *lab) const { return lab->view(1); } + + auto checkCalc73(const EventLabel *lab) const; + mutable std::vector visitedCoherence_0; + mutable std::vector visitedCoherence_1; + mutable std::vector visitedCoherence_2; + mutable std::vector visitedCoherence_3; + mutable std::vector visitedCoherence_4; + mutable std::vector visitedCoherence_5; + mutable std::vector visitedCoherence_6; + mutable uint32_t visitedCoherenceAccepting; + + bool visitCoherence_0(const EventLabel *lab) const; + bool visitCoherence_1(const EventLabel *lab) const; + bool visitCoherence_2(const EventLabel *lab) const; + bool visitCoherence_3(const EventLabel *lab) const; + bool visitCoherence_4(const EventLabel *lab) const; + bool visitCoherence_5(const EventLabel *lab) const; + bool visitCoherence_6(const EventLabel *lab) const; + + bool visitCoherenceFull() const; + + mutable std::vector visitedConsAcyclic1_0; + mutable std::vector visitedConsAcyclic1_1; + mutable std::vector visitedConsAcyclic1_2; + mutable std::vector visitedConsAcyclic1_3; + mutable std::vector visitedConsAcyclic1_4; + mutable std::vector visitedConsAcyclic1_5; + mutable std::vector visitedConsAcyclic1_6; + mutable std::vector visitedConsAcyclic1_7; + mutable std::vector visitedConsAcyclic1_8; + mutable std::vector visitedConsAcyclic1_9; + mutable std::vector visitedConsAcyclic1_10; + mutable std::vector visitedConsAcyclic1_11; + mutable std::vector visitedConsAcyclic1_12; + mutable std::vector visitedConsAcyclic1_13; + mutable std::vector visitedConsAcyclic1_14; + mutable std::vector visitedConsAcyclic1_15; + mutable std::vector visitedConsAcyclic1_16; + mutable std::vector visitedConsAcyclic1_17; + mutable std::vector visitedConsAcyclic1_18; + mutable std::vector visitedConsAcyclic1_19; + mutable std::vector visitedConsAcyclic1_20; + mutable std::vector visitedConsAcyclic1_21; + mutable uint32_t visitedConsAcyclic1Accepting; + + bool visitConsAcyclic1_0(const EventLabel *lab) const; + bool visitConsAcyclic1_1(const EventLabel *lab) const; + bool visitConsAcyclic1_2(const EventLabel *lab) const; + bool visitConsAcyclic1_3(const EventLabel *lab) const; + bool visitConsAcyclic1_4(const EventLabel *lab) const; + bool visitConsAcyclic1_5(const EventLabel *lab) const; + bool visitConsAcyclic1_6(const EventLabel *lab) const; + bool visitConsAcyclic1_7(const EventLabel *lab) const; + bool visitConsAcyclic1_8(const EventLabel *lab) const; + bool visitConsAcyclic1_9(const EventLabel *lab) const; + bool visitConsAcyclic1_10(const EventLabel *lab) const; + bool visitConsAcyclic1_11(const EventLabel *lab) const; + bool visitConsAcyclic1_12(const EventLabel *lab) const; + bool visitConsAcyclic1_13(const EventLabel *lab) const; + bool visitConsAcyclic1_14(const EventLabel *lab) const; + bool visitConsAcyclic1_15(const EventLabel *lab) const; + bool visitConsAcyclic1_16(const EventLabel *lab) const; + bool visitConsAcyclic1_17(const EventLabel *lab) const; + bool visitConsAcyclic1_18(const EventLabel *lab) const; + bool visitConsAcyclic1_19(const EventLabel *lab) const; + bool visitConsAcyclic1_20(const EventLabel *lab) const; + bool visitConsAcyclic1_21(const EventLabel *lab) const; + + bool visitConsAcyclic1(const EventLabel *lab) const; + + bool visitConsAcyclic1Full() const; + + mutable std::vector visitedLHSUnlessConsAcyclic1_0; + mutable std::vector visitedLHSUnlessConsAcyclic1_1; + + bool visitLHSUnlessConsAcyclic1_0(const EventLabel *lab) const; + bool visitLHSUnlessConsAcyclic1_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessConsAcyclic1Accepting; + mutable std::vector visitedRHSUnlessConsAcyclic1Accepting; + bool visitUnlessConsAcyclic1(const EventLabel *lab) const; + bool checkConsAcyclic1(const EventLabel *lab) const; + mutable std::vector visitedConsAcyclic2_0; + mutable std::vector visitedConsAcyclic2_1; + mutable std::vector visitedConsAcyclic2_2; + mutable std::vector visitedConsAcyclic2_3; + mutable std::vector visitedConsAcyclic2_4; + mutable std::vector visitedConsAcyclic2_5; + mutable std::vector visitedConsAcyclic2_6; + mutable std::vector visitedConsAcyclic2_7; + mutable std::vector visitedConsAcyclic2_8; + mutable std::vector visitedConsAcyclic2_9; + mutable std::vector visitedConsAcyclic2_10; + mutable std::vector visitedConsAcyclic2_11; + mutable std::vector visitedConsAcyclic2_12; + mutable std::vector visitedConsAcyclic2_13; + mutable std::vector visitedConsAcyclic2_14; + mutable std::vector visitedConsAcyclic2_15; + mutable std::vector visitedConsAcyclic2_16; + mutable std::vector visitedConsAcyclic2_17; + mutable std::vector visitedConsAcyclic2_18; + mutable std::vector visitedConsAcyclic2_19; + mutable uint32_t visitedConsAcyclic2Accepting; + + bool visitConsAcyclic2_0(const EventLabel *lab) const; + bool visitConsAcyclic2_1(const EventLabel *lab) const; + bool visitConsAcyclic2_2(const EventLabel *lab) const; + bool visitConsAcyclic2_3(const EventLabel *lab) const; + bool visitConsAcyclic2_4(const EventLabel *lab) const; + bool visitConsAcyclic2_5(const EventLabel *lab) const; + bool visitConsAcyclic2_6(const EventLabel *lab) const; + bool visitConsAcyclic2_7(const EventLabel *lab) const; + bool visitConsAcyclic2_8(const EventLabel *lab) const; + bool visitConsAcyclic2_9(const EventLabel *lab) const; + bool visitConsAcyclic2_10(const EventLabel *lab) const; + bool visitConsAcyclic2_11(const EventLabel *lab) const; + bool visitConsAcyclic2_12(const EventLabel *lab) const; + bool visitConsAcyclic2_13(const EventLabel *lab) const; + bool visitConsAcyclic2_14(const EventLabel *lab) const; + bool visitConsAcyclic2_15(const EventLabel *lab) const; + bool visitConsAcyclic2_16(const EventLabel *lab) const; + bool visitConsAcyclic2_17(const EventLabel *lab) const; + bool visitConsAcyclic2_18(const EventLabel *lab) const; + bool visitConsAcyclic2_19(const EventLabel *lab) const; + + bool visitConsAcyclic2(const EventLabel *lab) const; + + bool visitConsAcyclic2Full() const; + + bool checkUnlessConsAcyclic2(const EventLabel *lab) { return false; } + bool checkConsAcyclic2(const EventLabel *lab) const; + bool visitWarning3(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessWarning3_0; + mutable std::vector visitedLHSUnlessWarning3_1; + + bool visitLHSUnlessWarning3_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessWarning3_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessWarning3Accepting; + bool visitUnlessWarning3(const EventLabel *lab) const; + bool checkWarning3(const EventLabel *lab) const; + + void visitPPoRf0(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf1(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf2(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf3(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf4(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf5(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf6(const EventLabel *lab, DepView &pporf) const; + void visitPPoRf7(const EventLabel *lab, DepView &pporf) const; + + DepView calcPPoRfBefore(const EventLabel *lab) const; + + mutable std::vector visitedPPoRf0; + mutable std::vector visitedPPoRf1; + mutable std::vector visitedPPoRf2; + mutable std::vector visitedPPoRf3; + mutable std::vector visitedPPoRf4; + mutable std::vector visitedPPoRf5; + mutable std::vector visitedPPoRf6; + mutable std::vector visitedPPoRf7; + + +}; + +#endif /* GENMC_IMM_DRIVER_HPP */ diff --git a/src/Verification/Consistency/RADriver.cpp b/src/Verification/Consistency/RADriver.cpp new file mode 100644 index 0000000..6872cb6 --- /dev/null +++ b/src/Verification/Consistency/RADriver.cpp @@ -0,0 +1,1857 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#include "RADriver.hpp" +#include "Static/ModuleInfo.hpp" + +RADriver::RADriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) + : GenMCDriver(conf, std::move(mod), std::move(MI), mode) {} + +bool RADriver::isDepTracking() const +{ + return 0; +} + +bool RADriver::visitCalc61_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool RADriver::visitCalc61_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitCalc61_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_2[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_2[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + + visitedCalc61_2[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RADriver::visitCalc61_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_3[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_3[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc61_3[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RADriver::visitCalc61_4(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_4[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_4[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc61_4[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RADriver::visitCalc61_5(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc61_5[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc61_5[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc61_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc61_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc61_5[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RADriver::visitCalc61_6(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc61_7(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc61_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto status = visitedCalc61_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc61_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitCalc61_7(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc61_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc61_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View RADriver::visitCalc61(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + visitedCalc61_2.clear(); + visitedCalc61_2.resize(g.getMaxStamp().get() + 1); + visitedCalc61_3.clear(); + visitedCalc61_3.resize(g.getMaxStamp().get() + 1); + visitedCalc61_4.clear(); + visitedCalc61_4.resize(g.getMaxStamp().get() + 1); + visitedCalc61_5.clear(); + visitedCalc61_5.resize(g.getMaxStamp().get() + 1); + + visitCalc61_6(lab, calcRes); + return calcRes; +} +auto RADriver::checkCalc61(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc61(lab); +} +bool RADriver::visitCalc67_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool RADriver::visitCalc67_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(1)); true) { + if (!visitCalc67_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitCalc67_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc67_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc67_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc67_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc67_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc67_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc67_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitCalc67_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc67_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc67_2(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc67_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View RADriver::visitCalc67(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc67_3(lab, calcRes); + return calcRes; +} +auto RADriver::checkCalc67(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc67(lab); +} +void RADriver::calculateSaved(EventLabel *lab) +{ +} + +void RADriver::calculateViews(EventLabel *lab) +{ + lab->addView(checkCalc61(lab)); + lab->addView(checkCalc67(lab)); +} + +void RADriver::updateMMViews(EventLabel *lab) +{ + calculateViews(lab); + calculateSaved(lab); + lab->setPrefixView(calculatePrefixView(lab)); +} + +const View &RADriver::getHbView(const EventLabel *lab) const +{ + return lab->view(0); +} + + +bool RADriver::isWriteRfBefore(Event a, Event b) +{ + auto &g = getGraph(); + auto &before = g.getEventLabel(b)->view(0); + if (before.contains(a)) + return true; + + const EventLabel *lab = g.getEventLabel(a); + + BUG_ON(!llvm::isa(lab)); + auto *wLab = static_cast(lab); + for (auto &rLab : wLab->readers()) + if (before.contains(rLab.getPos())) + return true; + return false; +} + +std::vector +RADriver::getInitRfsAtLoc(SAddr addr) +{ + std::vector result; + + for (const auto &lab : getGraph().labels()) { + if (auto *rLab = llvm::dyn_cast(&lab)) + if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) + result.push_back(rLab->getPos()); + } + return result; +} + +bool RADriver::isHbOptRfBefore(const Event e, const Event write) +{ + auto &g = getGraph(); + const EventLabel *lab = g.getEventLabel(write); + + BUG_ON(!llvm::isa(lab)); + auto *sLab = static_cast(lab); + if (sLab->view(0).contains(e)) + return true; + + for (auto &rLab : sLab->readers()) { + if (rLab.view(0).contains(e)) + return true; + } + return false; +} + +ExecutionGraph::co_iterator +RADriver::splitLocMOBefore(SAddr addr, Event e) +{ + auto &g = getGraph(); + auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), [&](auto &lab){ + return isWriteRfBefore(lab.getPos(), e); + }); + /* Convert to forward iterator, but be _really_ careful */ + if (rit == g.co_rend(addr)) + return g.co_begin(addr); + return ++ExecutionGraph::co_iterator(*rit); +} + +ExecutionGraph::co_iterator +RADriver::splitLocMOAfterHb(SAddr addr, const Event read) +{ + auto &g = getGraph(); + + auto initRfs = g.getInitRfsAtLoc(addr); + if (std::any_of(initRfs.begin(), initRfs.end(), [&read,&g](const Event &rf){ + return g.getEventLabel(rf)->view(0).contains(read); + })) + return g.co_begin(addr); + + auto it = std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(read, lab.getPos()); + }); + if (it == g.co_end(addr) || it->view(0).contains(read)) + return it; + return ++it; +} + +ExecutionGraph::co_iterator +RADriver::splitLocMOAfter(SAddr addr, const Event e) +{ + auto &g = getGraph(); + return std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(e, lab.getPos()); + }); +} + +std::vector +RADriver::getCoherentStores(SAddr addr, Event read) +{ + auto &g = getGraph(); + std::vector stores; + + /* Fastpath: co_max(G) is po-before R */ + auto comax = g.co_rbegin(addr) == g.co_rend(addr) ? Event::getInit() : + g.co_rbegin(addr)->getPos(); + if (comax.thread == read.thread && comax.index < read.index) + return {comax}; + + /* + * If there are no stores (rf?;hb)-before the current event + * then we can read read from all concurrent stores and the + * initializer store. Otherwise, we can read from all concurrent + * stores and the mo-latest of the (rf?;hb)-before stores. + */ + auto begIt = splitLocMOBefore(addr, read); + if (begIt == g.co_begin(addr)) + stores.push_back(Event::getInit()); + else { + stores.push_back((--begIt)->getPos()); + ++begIt; + } + + /* + * If the model supports out-of-order execution we have to also + * account for the possibility the read is hb-before some other + * store, or some read that reads from a store. + */ + auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); + std::transform(begIt, endIt, std::back_inserter(stores), [&](auto &lab){ + return lab.getPos(); + }); + return stores; +} + +std::vector +RADriver::getMOOptRfAfter(const WriteLabel *sLab) +{ + std::vector after; + std::vector rfAfter; + + const auto &g = getGraph(); + std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), + [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + return after; +} + +std::vector +RADriver::getMOInvOptRfAfter(const WriteLabel *sLab) +{ + auto &g = getGraph(); + std::vector after; + std::vector rfAfter; + + /* First, add (mo;rf?)-before */ + std::for_each(g.co_pred_begin(sLab), + g.co_pred_end(sLab), [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + + /* Then, we add the reader list for the initializer */ + auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); + after.insert(after.end(), initRfs.begin(), initRfs.end()); + return after; +} + +static std::vector +getRevisitableFrom(const ExecutionGraph &g, const WriteLabel *sLab, + const VectorClock &pporf, const WriteLabel *coPred) +{ + auto pendingRMW = g.getPendingRMW(sLab); + std::vector loads; + + for (auto &rLab : coPred->readers()) { + if (!pporf.contains(rLab.getPos()) && rLab.getAddr() == sLab->getAddr() && + rLab.isRevisitable() && rLab.wasAddedMax()) + loads.push_back(rLab.getPos()); + } + if (!pendingRMW.isInitializer()) + loads.erase(std::remove_if(loads.begin(), loads.end(), + [&](Event &e) { + auto *confLab = g.getEventLabel(pendingRMW); + return g.getEventLabel(e)->getStamp() > + confLab->getStamp(); + }), + loads.end()); + return loads; +} + +std::vector +RADriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) +{ + auto &g = getGraph(); + std::vector ls; + + /* Fastpath: previous co-max is ppo-before SLAB */ + auto prevCoMaxIt = std::find_if(g.co_rbegin(sLab->getAddr()), g.co_rend(sLab->getAddr()), + [&](auto &lab) { return lab.getPos() != sLab->getPos(); }); + if (prevCoMaxIt != g.co_rend(sLab->getAddr()) && pporf.contains(prevCoMaxIt->getPos())) { + ls = getRevisitableFrom(g, sLab, pporf, &*prevCoMaxIt); + } else { + ls = g.getRevisitable(sLab, pporf); + } + + /* If this store is po- and mo-maximal then we are done */ + if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) + return ls; + + /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ + auto optRfs = getMOOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { const View &before = g.getEventLabel(e)->view(0); + return std::any_of(optRfs.begin(), optRfs.end(), + [&](Event ev) + { return before.contains(ev); }); + }), ls.end()); + + /* If out-of-order event addition is not supported, then we are done + * due to po-maximality */ + if (!isDepTracking()) + return ls; + + /* Otherwise, we also have to exclude hb-before loads */ + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { return g.getEventLabel(sLab->getPos())->view(0).contains(e); }), + ls.end()); + + /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in + * the resulting graph */ + auto &before = pporf; + auto moInvOptRfs = getMOInvOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { auto *eLab = g.getEventLabel(e); + auto v = g.getViewFromStamp(eLab->getStamp()); + v->update(before); + return std::any_of(moInvOptRfs.begin(), + moInvOptRfs.end(), + [&](Event ev) + { return v->contains(ev) && + g.getEventLabel(ev)->view(0).contains(e); }); + }), + ls.end()); + + return ls; +} + +std::vector +RADriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) +{ + auto &g = getGraph(); + std::vector result; + + /* If it is an RMW store, there is only one possible position in MO */ + if (isRMW) { + auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev())); + BUG_ON(!rLab); + auto *rfLab = rLab->getRf(); + BUG_ON(!rfLab); + result.push_back(rfLab->getPos()); + return result; + } + + /* Otherwise, we calculate the full range and add the store */ + auto rangeBegin = splitLocMOBefore(addr, store); + auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); + auto cos = llvm::iterator_range(rangeBegin, rangeEnd) | + std::views::filter([&](auto &sLab) { return !g.isRMWStore(sLab.getPos()); }) | + std::views::transform([&](auto &sLab) { + auto *pLab = g.co_imm_pred(&sLab); + return pLab ? pLab->getPos() : Event::getInit(); + }); + std::ranges::copy(cos, std::back_inserter(result)); + result.push_back(rangeEnd == g.co_end(addr) ? g.co_max(addr)->getPos() + : !g.co_imm_pred(&*rangeEnd) ? Event::getInit() + : g.co_imm_pred(&*rangeEnd)->getPos()); + return result; +} +bool RADriver::visitCoherence_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedCoherenceAccepting; + + + --visitedCoherenceAccepting; + return true; +} + +bool RADriver::visitCoherence_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_6(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RADriver::visitCoherence_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RADriver::visitCoherence_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RADriver::visitCoherence_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RADriver::visitCoherence_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RADriver::visitCoherence_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool RADriver::visitCoherenceFull() const +{ + auto &g = getGraph(); + + visitedCoherenceAccepting = 0; + visitedCoherence_1.clear(); + visitedCoherence_1.resize(g.getMaxStamp().get() + 1); + visitedCoherence_2.clear(); + visitedCoherence_2.resize(g.getMaxStamp().get() + 1); + visitedCoherence_3.clear(); + visitedCoherence_3.resize(g.getMaxStamp().get() + 1); + visitedCoherence_4.clear(); + visitedCoherence_4.resize(g.getMaxStamp().get() + 1); + visitedCoherence_5.clear(); + visitedCoherence_5.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedCoherence_1[lab.getStamp().get()].status != NodeStatus::unseen || visitCoherence_1(&lab); }); +} + +bool RADriver::visitError1(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError1_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RADriver::visitLHSUnlessError1_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError1_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError1Accepting.clear(); + visitedLHSUnlessError1Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError1_1(lab, v); +} + +bool RADriver::checkError1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError1(lab)) + return true; + + return visitError1(lab); +} +bool RADriver::visitError2(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError2_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RADriver::visitLHSUnlessError2_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError2_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError2_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError2_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError2_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError2Accepting.clear(); + visitedLHSUnlessError2Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError2Accepting.clear(); + visitedRHSUnlessError2Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError2_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError2Accepting.size(); i++) { + if (visitedLHSUnlessError2Accepting[i] && !visitedRHSUnlessError2Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RADriver::checkError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError2(lab)) + return true; + + return visitError2(lab); +} +bool RADriver::visitError3(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError3_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RADriver::visitLHSUnlessError3_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true) { + if (!visitLHSUnlessError3_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitLHSUnlessError3_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError3_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError3_1(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError3Accepting.clear(); + visitedLHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError3_2(lab, v); +} + +bool RADriver::checkError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError3(lab)) + return true; + + return visitError3(lab); +} +bool RADriver::visitError4(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError4_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RADriver::visitLHSUnlessError4_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError4_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitLHSUnlessError4_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_1(pLab)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError4Accepting.clear(); + visitedLHSUnlessError4Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError4Accepting.clear(); + visitedRHSUnlessError4Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError4_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError4Accepting.size(); i++) { + if (visitedLHSUnlessError4Accepting[i] && !visitedRHSUnlessError4Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RADriver::checkError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError4(lab)) + return true; + + return visitError4(lab); +} +bool RADriver::visitError5(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError5_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RADriver::visitLHSUnlessError5_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError5_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitLHSUnlessError5_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError5_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError5_1(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError5Accepting.clear(); + visitedLHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError5_2(lab, v); +} + +bool RADriver::checkError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError5(lab)) + return true; + + return visitError5(lab); +} +bool RADriver::visitError6(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError6_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RADriver::visitLHSUnlessError6_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError6_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitLHSUnlessError6_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && llvm::dyn_cast(lab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(lab)))if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError6_1(pLab)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError6Accepting.clear(); + visitedLHSUnlessError6Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError6Accepting.clear(); + visitedRHSUnlessError6Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError6_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError6Accepting.size(); i++) { + if (visitedLHSUnlessError6Accepting[i] && !visitedRHSUnlessError6Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RADriver::checkError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError6(lab)) + return true; + + return visitError6(lab); +} +bool RADriver::visitError7(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessError7_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RADriver::visitLHSUnlessError7_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError7Accepting.clear(); + visitedLHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError7_1(lab, v); +} + +bool RADriver::checkError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError7(lab)) + return true; + + return visitError7(lab); +} +bool RADriver::visitWarning8(const EventLabel *lab) const +{ + return false; +} + +bool RADriver::visitLHSUnlessWarning8_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RADriver::visitLHSUnlessWarning8_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessWarning8_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RADriver::visitUnlessWarning8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessWarning8Accepting.clear(); + visitedLHSUnlessWarning8Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessWarning8_1(lab, v); +} + +bool RADriver::checkWarning8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessWarning8(lab)) + return true; + + return visitWarning8(lab); +} +VerificationError RADriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const +{ + if (!checkError1(lab)) { + race = cexLab; + return VerificationError::VE_AccessNonMalloc; + } + + if (!checkError2(lab)) { + race = cexLab; + return VerificationError::VE_DoubleFree; + } + + if (!checkError3(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError4(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError5(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError6(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError7(lab)) { + race = cexLab; + return VerificationError::VE_RaceNotAtomic; + } + + return VerificationError::VE_OK; +} + +std::vector RADriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const +{ + std::vector result; + + if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkWarning8(lab)) { + racyLabs.push_back(cexLab); + result.push_back(VerificationError::VE_WWRace); + } + + return result; +} + +bool RADriver::isConsistent(const EventLabel *lab) const +{ + + return true; +} + +View RADriver::calcPPoRfBefore(const EventLabel *lab) const +{ + auto &g = getGraph(); + View pporf; + pporf.updateIdx(lab->getPos()); + + auto *pLab = g.getPreviousLabel(lab); + if (!pLab) + return pporf; + pporf.update(pLab->getPrefixView()); + if (auto *rLab = llvm::dyn_cast(pLab)) + pporf.update(rLab->getRf()->getPrefixView()); + if (auto *tsLab = llvm::dyn_cast(pLab)) + pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); + if (auto *tjLab = llvm::dyn_cast(pLab)) + pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); + return pporf; +} +std::unique_ptr RADriver::calculatePrefixView(const EventLabel *lab) const +{ + return std::make_unique(calcPPoRfBefore(lab)); +} diff --git a/src/Verification/Consistency/RADriver.hpp b/src/Verification/Consistency/RADriver.hpp new file mode 100644 index 0000000..a482542 --- /dev/null +++ b/src/Verification/Consistency/RADriver.hpp @@ -0,0 +1,242 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#ifndef GENMC_RA_DRIVER_HPP +#define GENMC_RA_DRIVER_HPP + +#include "config.h" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Verification/GenMCDriver.hpp" +#include "Verification/VerificationError.hpp" +#include +#include + +class RADriver : public GenMCDriver { + +private: + enum class NodeStatus : unsigned char { unseen, entered, left }; + + struct NodeVisitStatus { + NodeVisitStatus() = default; + NodeVisitStatus(uint32_t c, NodeStatus s) : count(c), status(s) {} + uint32_t count{}; + NodeStatus status{}; + }; + +public: + RADriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); + + void calculateSaved(EventLabel *lab); + void calculateViews(EventLabel *lab); + void updateMMViews(EventLabel *lab) override; + bool isDepTracking() const override; + bool isConsistent(const EventLabel *lab) const override; + VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const override; + std::vector checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const; + std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; + const View &getHbView(const EventLabel *lab) const override; + std::vector getCoherentStores(SAddr addr, Event read) override; + std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) override; + std::vector getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; + +private: + bool isWriteRfBefore(Event a, Event b); + std::vector getInitRfsAtLoc(SAddr addr); + bool isHbOptRfBefore(const Event e, const Event write); + ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); + ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); + ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); + std::vector getMOOptRfAfter(const WriteLabel *sLab); + std::vector getMOInvOptRfAfter(const WriteLabel *sLab); + mutable const EventLabel *cexLab{}; + + mutable std::vector visitedCalc61_0; + mutable std::vector visitedCalc61_1; + mutable std::vector visitedCalc61_2; + mutable std::vector visitedCalc61_3; + mutable std::vector visitedCalc61_4; + mutable std::vector visitedCalc61_5; + mutable std::vector visitedCalc61_6; + mutable std::vector visitedCalc61_7; + + bool visitCalc61_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_3(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_4(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_5(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_6(const EventLabel *lab, View &calcRes) const; + bool visitCalc61_7(const EventLabel *lab, View &calcRes) const; + + View visitCalc61(const EventLabel *lab) const; + const View&getHbStableView(const EventLabel *lab) const { return lab->view(0); } + + auto checkCalc61(const EventLabel *lab) const; + mutable std::vector visitedCalc67_0; + mutable std::vector visitedCalc67_1; + mutable std::vector visitedCalc67_2; + mutable std::vector visitedCalc67_3; + + bool visitCalc67_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc67_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc67_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc67_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc67(const EventLabel *lab) const; + const View&getPorfStableView(const EventLabel *lab) const { return lab->view(1); } + + auto checkCalc67(const EventLabel *lab) const; + mutable std::vector visitedCoherence_0; + mutable std::vector visitedCoherence_1; + mutable std::vector visitedCoherence_2; + mutable std::vector visitedCoherence_3; + mutable std::vector visitedCoherence_4; + mutable std::vector visitedCoherence_5; + mutable std::vector visitedCoherence_6; + mutable uint32_t visitedCoherenceAccepting; + + bool visitCoherence_0(const EventLabel *lab) const; + bool visitCoherence_1(const EventLabel *lab) const; + bool visitCoherence_2(const EventLabel *lab) const; + bool visitCoherence_3(const EventLabel *lab) const; + bool visitCoherence_4(const EventLabel *lab) const; + bool visitCoherence_5(const EventLabel *lab) const; + bool visitCoherence_6(const EventLabel *lab) const; + + bool visitCoherenceFull() const; + + bool visitError1(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError1_0; + mutable std::vector visitedLHSUnlessError1_1; + + bool visitLHSUnlessError1_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError1_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError1Accepting; + bool visitUnlessError1(const EventLabel *lab) const; + bool checkError1(const EventLabel *lab) const; + bool visitError2(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError2_0; + mutable std::vector visitedLHSUnlessError2_1; + + bool visitLHSUnlessError2_0(const EventLabel *lab) const; + bool visitLHSUnlessError2_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError2Accepting; + mutable std::vector visitedRHSUnlessError2Accepting; + bool visitUnlessError2(const EventLabel *lab) const; + bool checkError2(const EventLabel *lab) const; + bool visitError3(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError3_0; + mutable std::vector visitedLHSUnlessError3_1; + mutable std::vector visitedLHSUnlessError3_2; + + bool visitLHSUnlessError3_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError3_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError3_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError3Accepting; + bool visitUnlessError3(const EventLabel *lab) const; + bool checkError3(const EventLabel *lab) const; + bool visitError4(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError4_0; + mutable std::vector visitedLHSUnlessError4_1; + mutable std::vector visitedLHSUnlessError4_2; + + bool visitLHSUnlessError4_0(const EventLabel *lab) const; + bool visitLHSUnlessError4_1(const EventLabel *lab) const; + bool visitLHSUnlessError4_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError4Accepting; + mutable std::vector visitedRHSUnlessError4Accepting; + bool visitUnlessError4(const EventLabel *lab) const; + bool checkError4(const EventLabel *lab) const; + bool visitError5(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError5_0; + mutable std::vector visitedLHSUnlessError5_1; + mutable std::vector visitedLHSUnlessError5_2; + + bool visitLHSUnlessError5_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError5_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError5_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError5Accepting; + bool visitUnlessError5(const EventLabel *lab) const; + bool checkError5(const EventLabel *lab) const; + bool visitError6(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError6_0; + mutable std::vector visitedLHSUnlessError6_1; + mutable std::vector visitedLHSUnlessError6_2; + + bool visitLHSUnlessError6_0(const EventLabel *lab) const; + bool visitLHSUnlessError6_1(const EventLabel *lab) const; + bool visitLHSUnlessError6_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError6Accepting; + mutable std::vector visitedRHSUnlessError6Accepting; + bool visitUnlessError6(const EventLabel *lab) const; + bool checkError6(const EventLabel *lab) const; + bool visitError7(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError7_0; + mutable std::vector visitedLHSUnlessError7_1; + + bool visitLHSUnlessError7_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError7_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError7Accepting; + bool visitUnlessError7(const EventLabel *lab) const; + bool checkError7(const EventLabel *lab) const; + bool visitWarning8(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessWarning8_0; + mutable std::vector visitedLHSUnlessWarning8_1; + + bool visitLHSUnlessWarning8_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessWarning8_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessWarning8Accepting; + bool visitUnlessWarning8(const EventLabel *lab) const; + bool checkWarning8(const EventLabel *lab) const; + + void visitPPoRf0(const EventLabel *lab, View &pporf) const; + void visitPPoRf1(const EventLabel *lab, View &pporf) const; + + View calcPPoRfBefore(const EventLabel *lab) const; + + mutable std::vector visitedPPoRf0; + mutable std::vector visitedPPoRf1; + + +}; + +#endif /* GENMC_RA_DRIVER_HPP */ diff --git a/src/Verification/Consistency/RC11Driver.cpp b/src/Verification/Consistency/RC11Driver.cpp new file mode 100644 index 0000000..fb7fcb4 --- /dev/null +++ b/src/Verification/Consistency/RC11Driver.cpp @@ -0,0 +1,3854 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#include "RC11Driver.hpp" +#include "Static/ModuleInfo.hpp" + +RC11Driver::RC11Driver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) + : GenMCDriver(conf, std::move(mod), std::move(MI), mode) {} + +bool RC11Driver::isDepTracking() const +{ + return 0; +} + +bool RC11Driver::visitCalc58_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool RC11Driver::visitCalc58_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc58_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitCalc58_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc58_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc58_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc58_3(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitCalc58_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc58_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc58_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc58_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc58_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc58_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc58_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View RC11Driver::visitCalc58(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc58_2(lab, calcRes); + return calcRes; +} +auto RC11Driver::checkCalc58(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc58(lab); +} +bool RC11Driver::visitCalc64_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool RC11Driver::visitCalc64_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(1)); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitCalc64_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc64_2[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc64_2[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab))if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc64_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc64_2[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RC11Driver::visitCalc64_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc64_3[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc64_3[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc64_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc64_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc64_3[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RC11Driver::visitCalc64_4(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc64_4[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc64_4[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc64_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc64_4[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RC11Driver::visitCalc64_5(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + if (visitedCalc64_5[lab->getStamp().get()] != NodeStatus::unseen) + return true; + visitedCalc64_5[lab->getStamp().get()] = NodeStatus::entered; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto status = visitedCalc64_4[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_4(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc64_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease())if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto status = visitedCalc64_2[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_2(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + + visitedCalc64_5[lab->getStamp().get()] = NodeStatus::left; + return true; +} + +bool RC11Driver::visitCalc64_6(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc64_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto status = visitedCalc64_5[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_5(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto status = visitedCalc64_3[pLab->getStamp().get()]; + if (status == NodeStatus::unseen) { + if (!visitCalc64_3(pLab, calcRes)){ + return false; + } + + } else if (status == NodeStatus::entered) { + + } else if (status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc64_7(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitCalc64_7(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc64_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc64_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View RC11Driver::visitCalc64(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + visitedCalc64_2.clear(); + visitedCalc64_2.resize(g.getMaxStamp().get() + 1); + visitedCalc64_3.clear(); + visitedCalc64_3.resize(g.getMaxStamp().get() + 1); + visitedCalc64_4.clear(); + visitedCalc64_4.resize(g.getMaxStamp().get() + 1); + visitedCalc64_5.clear(); + visitedCalc64_5.resize(g.getMaxStamp().get() + 1); + + visitCalc64_6(lab, calcRes); + return calcRes; +} +auto RC11Driver::checkCalc64(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc64(lab); +} +void RC11Driver::calculateSaved(EventLabel *lab) +{ +} + +void RC11Driver::calculateViews(EventLabel *lab) +{ + lab->addView(checkCalc58(lab)); + lab->addView(checkCalc64(lab)); +} + +void RC11Driver::updateMMViews(EventLabel *lab) +{ + calculateViews(lab); + calculateSaved(lab); + lab->setPrefixView(calculatePrefixView(lab)); +} + +const View &RC11Driver::getHbView(const EventLabel *lab) const +{ + return lab->view(1); +} + + +bool RC11Driver::isWriteRfBefore(Event a, Event b) +{ + auto &g = getGraph(); + auto &before = g.getEventLabel(b)->view(1); + if (before.contains(a)) + return true; + + const EventLabel *lab = g.getEventLabel(a); + + BUG_ON(!llvm::isa(lab)); + auto *wLab = static_cast(lab); + for (auto &rLab : wLab->readers()) + if (before.contains(rLab.getPos())) + return true; + return false; +} + +std::vector +RC11Driver::getInitRfsAtLoc(SAddr addr) +{ + std::vector result; + + for (const auto &lab : getGraph().labels()) { + if (auto *rLab = llvm::dyn_cast(&lab)) + if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) + result.push_back(rLab->getPos()); + } + return result; +} + +bool RC11Driver::isHbOptRfBefore(const Event e, const Event write) +{ + auto &g = getGraph(); + const EventLabel *lab = g.getEventLabel(write); + + BUG_ON(!llvm::isa(lab)); + auto *sLab = static_cast(lab); + if (sLab->view(1).contains(e)) + return true; + + for (auto &rLab : sLab->readers()) { + if (rLab.view(1).contains(e)) + return true; + } + return false; +} + +ExecutionGraph::co_iterator +RC11Driver::splitLocMOBefore(SAddr addr, Event e) +{ + auto &g = getGraph(); + auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), [&](auto &lab){ + return isWriteRfBefore(lab.getPos(), e); + }); + /* Convert to forward iterator, but be _really_ careful */ + if (rit == g.co_rend(addr)) + return g.co_begin(addr); + return ++ExecutionGraph::co_iterator(*rit); +} + +ExecutionGraph::co_iterator +RC11Driver::splitLocMOAfterHb(SAddr addr, const Event read) +{ + auto &g = getGraph(); + + auto initRfs = g.getInitRfsAtLoc(addr); + if (std::any_of(initRfs.begin(), initRfs.end(), [&read,&g](const Event &rf){ + return g.getEventLabel(rf)->view(1).contains(read); + })) + return g.co_begin(addr); + + auto it = std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(read, lab.getPos()); + }); + if (it == g.co_end(addr) || it->view(1).contains(read)) + return it; + return ++it; +} + +ExecutionGraph::co_iterator +RC11Driver::splitLocMOAfter(SAddr addr, const Event e) +{ + auto &g = getGraph(); + return std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(e, lab.getPos()); + }); +} + +std::vector +RC11Driver::getCoherentStores(SAddr addr, Event read) +{ + auto &g = getGraph(); + std::vector stores; + + /* Fastpath: co_max(G) is po-before R */ + auto comax = g.co_rbegin(addr) == g.co_rend(addr) ? Event::getInit() : + g.co_rbegin(addr)->getPos(); + if (comax.thread == read.thread && comax.index < read.index) + return {comax}; + + /* + * If there are no stores (rf?;hb)-before the current event + * then we can read read from all concurrent stores and the + * initializer store. Otherwise, we can read from all concurrent + * stores and the mo-latest of the (rf?;hb)-before stores. + */ + auto begIt = splitLocMOBefore(addr, read); + if (begIt == g.co_begin(addr)) + stores.push_back(Event::getInit()); + else { + stores.push_back((--begIt)->getPos()); + ++begIt; + } + + /* + * If the model supports out-of-order execution we have to also + * account for the possibility the read is hb-before some other + * store, or some read that reads from a store. + */ + auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); + std::transform(begIt, endIt, std::back_inserter(stores), [&](auto &lab){ + return lab.getPos(); + }); + return stores; +} + +std::vector +RC11Driver::getMOOptRfAfter(const WriteLabel *sLab) +{ + std::vector after; + std::vector rfAfter; + + const auto &g = getGraph(); + std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), + [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + return after; +} + +std::vector +RC11Driver::getMOInvOptRfAfter(const WriteLabel *sLab) +{ + auto &g = getGraph(); + std::vector after; + std::vector rfAfter; + + /* First, add (mo;rf?)-before */ + std::for_each(g.co_pred_begin(sLab), + g.co_pred_end(sLab), [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + + /* Then, we add the reader list for the initializer */ + auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); + after.insert(after.end(), initRfs.begin(), initRfs.end()); + return after; +} + +static std::vector +getRevisitableFrom(const ExecutionGraph &g, const WriteLabel *sLab, + const VectorClock &pporf, const WriteLabel *coPred) +{ + auto pendingRMW = g.getPendingRMW(sLab); + std::vector loads; + + for (auto &rLab : coPred->readers()) { + if (!pporf.contains(rLab.getPos()) && rLab.getAddr() == sLab->getAddr() && + rLab.isRevisitable() && rLab.wasAddedMax()) + loads.push_back(rLab.getPos()); + } + if (!pendingRMW.isInitializer()) + loads.erase(std::remove_if(loads.begin(), loads.end(), + [&](Event &e) { + auto *confLab = g.getEventLabel(pendingRMW); + return g.getEventLabel(e)->getStamp() > + confLab->getStamp(); + }), + loads.end()); + return loads; +} + +std::vector +RC11Driver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) +{ + auto &g = getGraph(); + std::vector ls; + + /* Fastpath: previous co-max is ppo-before SLAB */ + auto prevCoMaxIt = std::find_if(g.co_rbegin(sLab->getAddr()), g.co_rend(sLab->getAddr()), + [&](auto &lab) { return lab.getPos() != sLab->getPos(); }); + if (prevCoMaxIt != g.co_rend(sLab->getAddr()) && pporf.contains(prevCoMaxIt->getPos())) { + ls = getRevisitableFrom(g, sLab, pporf, &*prevCoMaxIt); + } else { + ls = g.getRevisitable(sLab, pporf); + } + + /* If this store is po- and mo-maximal then we are done */ + if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) + return ls; + + /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ + auto optRfs = getMOOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { const View &before = g.getEventLabel(e)->view(1); + return std::any_of(optRfs.begin(), optRfs.end(), + [&](Event ev) + { return before.contains(ev); }); + }), ls.end()); + + /* If out-of-order event addition is not supported, then we are done + * due to po-maximality */ + if (!isDepTracking()) + return ls; + + /* Otherwise, we also have to exclude hb-before loads */ + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { return g.getEventLabel(sLab->getPos())->view(1).contains(e); }), + ls.end()); + + /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in + * the resulting graph */ + auto &before = pporf; + auto moInvOptRfs = getMOInvOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { auto *eLab = g.getEventLabel(e); + auto v = g.getViewFromStamp(eLab->getStamp()); + v->update(before); + return std::any_of(moInvOptRfs.begin(), + moInvOptRfs.end(), + [&](Event ev) + { return v->contains(ev) && + g.getEventLabel(ev)->view(1).contains(e); }); + }), + ls.end()); + + return ls; +} + +std::vector +RC11Driver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) +{ + auto &g = getGraph(); + std::vector result; + + /* If it is an RMW store, there is only one possible position in MO */ + if (isRMW) { + auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev())); + BUG_ON(!rLab); + auto *rfLab = rLab->getRf(); + BUG_ON(!rfLab); + result.push_back(rfLab->getPos()); + return result; + } + + /* Otherwise, we calculate the full range and add the store */ + auto rangeBegin = splitLocMOBefore(addr, store); + auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); + auto cos = llvm::iterator_range(rangeBegin, rangeEnd) | + std::views::filter([&](auto &sLab) { return !g.isRMWStore(sLab.getPos()); }) | + std::views::transform([&](auto &sLab) { + auto *pLab = g.co_imm_pred(&sLab); + return pLab ? pLab->getPos() : Event::getInit(); + }); + std::ranges::copy(cos, std::back_inserter(result)); + result.push_back(rangeEnd == g.co_end(addr) ? g.co_max(addr)->getPos() + : !g.co_imm_pred(&*rangeEnd) ? Event::getInit() + : g.co_imm_pred(&*rangeEnd)->getPos()); + return result; +} +bool RC11Driver::visitCoherence_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedCoherenceAccepting; + + + --visitedCoherenceAccepting; + return true; +} + +bool RC11Driver::visitCoherence_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_6(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastAcquire()) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitCoherence_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease() && llvm::isa(pLab)) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_2[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitCoherence_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_3[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitCoherence_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_4[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitCoherence_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && pLab->isAtLeastRelease()) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab)if (true && llvm::isa(pLab) && ((llvm::isa(pLab) && g.isRMWLoad(pLab)) || (llvm::isa(pLab) && g.isRMWStore(pLab)))) { + auto &node = visitedCoherence_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_5[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitCoherence_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool RC11Driver::visitCoherenceFull() const +{ + auto &g = getGraph(); + + visitedCoherenceAccepting = 0; + visitedCoherence_1.clear(); + visitedCoherence_1.resize(g.getMaxStamp().get() + 1); + visitedCoherence_2.clear(); + visitedCoherence_2.resize(g.getMaxStamp().get() + 1); + visitedCoherence_3.clear(); + visitedCoherence_3.resize(g.getMaxStamp().get() + 1); + visitedCoherence_4.clear(); + visitedCoherence_4.resize(g.getMaxStamp().get() + 1); + visitedCoherence_5.clear(); + visitedCoherence_5.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedCoherence_1[lab.getStamp().get()].status != NodeStatus::unseen || visitCoherence_1(&lab); }); +} + +bool RC11Driver::visitConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_succ(g, lab); pLab) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool RC11Driver::visitConsAcyclic1_4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_4[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_4[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_4(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_4[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_5[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_5[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_6[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastRelease())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_5[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_5(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_6[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_7[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_7[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_8[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_7[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_7(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_8[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_9[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_9[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_10(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_10[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastAcquire())if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_succ(g, lab); pLab) { + if (!visitConsAcyclic1_11(pLab)){ + return false; + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = co_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = fr_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_10[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_11(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_10[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_10(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool RC11Driver::visitConsAcyclic1_12(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_12[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_12[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_12(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_12[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_13(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_13[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastRelease())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_13[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_14(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_14[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_14[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_15(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_15[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_15[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_16(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_16[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_succ(g, lab); pLab) { + if (!visitConsAcyclic1_17(pLab)){ + return false; + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_16[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_17(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool RC11Driver::visitConsAcyclic1_18(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_18[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_18[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_18(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isAtLeastAcquire() && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastAcquire() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_18[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_19(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_19[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_19[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_20(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_20[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (true && lab->isAtLeastRelease())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_16[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_16(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_19[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_19(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_20[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_20(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_20[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1_21(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedConsAcyclic1Accepting; + visitedConsAcyclic1_21[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + + if (true && lab->isSC())if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_14[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_14(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_8[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_8(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_9[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_9(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_6[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_6(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = co_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = fr_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC()) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_21[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_21(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isAtLeastRelease() && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_15[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_15(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC())if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_13[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_13(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + --visitedConsAcyclic1Accepting; + visitedConsAcyclic1_21[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool RC11Driver::visitConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_4.clear(); + visitedConsAcyclic1_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_5.clear(); + visitedConsAcyclic1_5.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_6.clear(); + visitedConsAcyclic1_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_7.clear(); + visitedConsAcyclic1_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_8.clear(); + visitedConsAcyclic1_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_9.clear(); + visitedConsAcyclic1_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_10.clear(); + visitedConsAcyclic1_10.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_12.clear(); + visitedConsAcyclic1_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_13.clear(); + visitedConsAcyclic1_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_14.clear(); + visitedConsAcyclic1_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_15.clear(); + visitedConsAcyclic1_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_16.clear(); + visitedConsAcyclic1_16.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_18.clear(); + visitedConsAcyclic1_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_19.clear(); + visitedConsAcyclic1_19.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_20.clear(); + visitedConsAcyclic1_20.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_21.clear(); + visitedConsAcyclic1_21.resize(g.getMaxStamp().get() + 1); + return true + && (visitedConsAcyclic1_6[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_6(lab)) + && (visitedConsAcyclic1_7[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_7(lab)) + && (visitedConsAcyclic1_8[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_8(lab)) + && (visitedConsAcyclic1_10[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_10(lab)) + && (visitedConsAcyclic1_13[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_13(lab)) + && (visitedConsAcyclic1_14[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_14(lab)) + && (visitedConsAcyclic1_20[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_20(lab)) + && (visitedConsAcyclic1_21[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_21(lab)); +} + +bool RC11Driver::visitConsAcyclic1Full() const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_4.clear(); + visitedConsAcyclic1_4.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_5.clear(); + visitedConsAcyclic1_5.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_6.clear(); + visitedConsAcyclic1_6.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_7.clear(); + visitedConsAcyclic1_7.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_8.clear(); + visitedConsAcyclic1_8.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_9.clear(); + visitedConsAcyclic1_9.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_10.clear(); + visitedConsAcyclic1_10.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_12.clear(); + visitedConsAcyclic1_12.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_13.clear(); + visitedConsAcyclic1_13.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_14.clear(); + visitedConsAcyclic1_14.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_15.clear(); + visitedConsAcyclic1_15.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_16.clear(); + visitedConsAcyclic1_16.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_18.clear(); + visitedConsAcyclic1_18.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_19.clear(); + visitedConsAcyclic1_19.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_20.clear(); + visitedConsAcyclic1_20.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_21.clear(); + visitedConsAcyclic1_21.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedConsAcyclic1_21[lab.getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_21(&lab); }); +} + +bool RC11Driver::visitLHSUnlessConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RC11Driver::visitLHSUnlessConsAcyclic1_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + for (auto &tmp : other_labels(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isSC()) { + if (!visitLHSUnlessConsAcyclic1_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessConsAcyclic1Accepting.clear(); + visitedLHSUnlessConsAcyclic1Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessConsAcyclic1Accepting.clear(); + visitedRHSUnlessConsAcyclic1Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessConsAcyclic1_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessConsAcyclic1Accepting.size(); i++) { + if (visitedLHSUnlessConsAcyclic1Accepting[i] && !visitedRHSUnlessConsAcyclic1Accepting[i]) { + return false; + } + } + return true; +} + +bool RC11Driver::checkConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessConsAcyclic1(lab)) + return true; + + return visitConsAcyclic1(lab); +} +bool RC11Driver::visitError2(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RC11Driver::visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError2_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError2Accepting.clear(); + visitedLHSUnlessError2Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessError2_1(lab, v); +} + +bool RC11Driver::checkError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError2(lab)) + return true; + + return visitError2(lab); +} +bool RC11Driver::visitError3(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError3_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RC11Driver::visitLHSUnlessError3_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError3Accepting.clear(); + visitedLHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError3Accepting.clear(); + visitedRHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError3_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError3Accepting.size(); i++) { + if (visitedLHSUnlessError3Accepting[i] && !visitedRHSUnlessError3Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RC11Driver::checkError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError3(lab)) + return true; + + return visitError3(lab); +} +bool RC11Driver::visitError4(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RC11Driver::visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_1(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError4Accepting.clear(); + visitedLHSUnlessError4Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessError4_2(lab, v); +} + +bool RC11Driver::checkError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError4(lab)) + return true; + + return visitError4(lab); +} +bool RC11Driver::visitError5(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError5_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RC11Driver::visitLHSUnlessError5_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError5_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitLHSUnlessError5_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError5_1(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError5Accepting.clear(); + visitedLHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError5Accepting.clear(); + visitedRHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError5_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError5Accepting.size(); i++) { + if (visitedLHSUnlessError5Accepting[i] && !visitedRHSUnlessError5Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RC11Driver::checkError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError5(lab)) + return true; + + return visitError5(lab); +} +bool RC11Driver::visitError6(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RC11Driver::visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError6_1(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError6Accepting.clear(); + visitedLHSUnlessError6Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessError6_2(lab, v); +} + +bool RC11Driver::checkError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError6(lab)) + return true; + + return visitError6(lab); +} +bool RC11Driver::visitError7(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError7_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool RC11Driver::visitLHSUnlessError7_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitLHSUnlessError7_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && llvm::dyn_cast(lab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(lab)))if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError7_1(pLab)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError7Accepting.clear(); + visitedLHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError7Accepting.clear(); + visitedRHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError7_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError7Accepting.size(); i++) { + if (visitedLHSUnlessError7Accepting[i] && !visitedRHSUnlessError7Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool RC11Driver::checkError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError7(lab)) + return true; + + return visitError7(lab); +} +bool RC11Driver::visitError8(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RC11Driver::visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError8Accepting.clear(); + visitedLHSUnlessError8Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessError8_1(lab, v); +} + +bool RC11Driver::checkError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError8(lab)) + return true; + + return visitError8(lab); +} +bool RC11Driver::visitWarning9(const EventLabel *lab) const +{ + return false; +} + +bool RC11Driver::visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool RC11Driver::visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessWarning9_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool RC11Driver::visitUnlessWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessWarning9Accepting.clear(); + visitedLHSUnlessWarning9Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessWarning9_1(lab, v); +} + +bool RC11Driver::checkWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessWarning9(lab)) + return true; + + return visitWarning9(lab); +} +VerificationError RC11Driver::checkErrors(const EventLabel *lab, const EventLabel *&race) const +{ + if (!checkError2(lab)) { + race = cexLab; + return VerificationError::VE_AccessNonMalloc; + } + + if (!checkError3(lab)) { + race = cexLab; + return VerificationError::VE_DoubleFree; + } + + if (!checkError4(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError5(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError6(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError7(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError8(lab)) { + race = cexLab; + return VerificationError::VE_RaceNotAtomic; + } + + return VerificationError::VE_OK; +} + +std::vector RC11Driver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const +{ + std::vector result; + + if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkWarning9(lab)) { + racyLabs.push_back(cexLab); + result.push_back(VerificationError::VE_WWRace); + } + + return result; +} + +bool RC11Driver::isConsistent(const EventLabel *lab) const +{ + + return true + && checkConsAcyclic1(lab); +} + +View RC11Driver::calcPPoRfBefore(const EventLabel *lab) const +{ + auto &g = getGraph(); + View pporf; + pporf.updateIdx(lab->getPos()); + + auto *pLab = g.getPreviousLabel(lab); + if (!pLab) + return pporf; + pporf.update(pLab->getPrefixView()); + if (auto *rLab = llvm::dyn_cast(pLab)) + pporf.update(rLab->getRf()->getPrefixView()); + if (auto *tsLab = llvm::dyn_cast(pLab)) + pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); + if (auto *tjLab = llvm::dyn_cast(pLab)) + pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); + return pporf; +} +std::unique_ptr RC11Driver::calculatePrefixView(const EventLabel *lab) const +{ + return std::make_unique(calcPPoRfBefore(lab)); +} diff --git a/src/Verification/Consistency/RC11Driver.hpp b/src/Verification/Consistency/RC11Driver.hpp new file mode 100644 index 0000000..0280c60 --- /dev/null +++ b/src/Verification/Consistency/RC11Driver.hpp @@ -0,0 +1,305 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#ifndef GENMC_RC11_DRIVER_HPP +#define GENMC_RC11_DRIVER_HPP + +#include "config.h" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Verification/GenMCDriver.hpp" +#include "Verification/VerificationError.hpp" +#include +#include + +class RC11Driver : public GenMCDriver { + +private: + enum class NodeStatus : unsigned char { unseen, entered, left }; + + struct NodeVisitStatus { + NodeVisitStatus() = default; + NodeVisitStatus(uint32_t c, NodeStatus s) : count(c), status(s) {} + uint32_t count{}; + NodeStatus status{}; + }; + +public: + RC11Driver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); + + void calculateSaved(EventLabel *lab); + void calculateViews(EventLabel *lab); + void updateMMViews(EventLabel *lab) override; + bool isDepTracking() const override; + bool isConsistent(const EventLabel *lab) const override; + VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const override; + std::vector checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const; + std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; + const View &getHbView(const EventLabel *lab) const override; + std::vector getCoherentStores(SAddr addr, Event read) override; + std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) override; + std::vector getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; + +private: + bool isWriteRfBefore(Event a, Event b); + std::vector getInitRfsAtLoc(SAddr addr); + bool isHbOptRfBefore(const Event e, const Event write); + ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); + ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); + ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); + std::vector getMOOptRfAfter(const WriteLabel *sLab); + std::vector getMOInvOptRfAfter(const WriteLabel *sLab); + mutable const EventLabel *cexLab{}; + + mutable std::vector visitedCalc58_0; + mutable std::vector visitedCalc58_1; + mutable std::vector visitedCalc58_2; + mutable std::vector visitedCalc58_3; + + bool visitCalc58_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc58_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc58_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc58_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc58(const EventLabel *lab) const; + const View&getPorfStableView(const EventLabel *lab) const { return lab->view(0); } + + auto checkCalc58(const EventLabel *lab) const; + mutable std::vector visitedCalc64_0; + mutable std::vector visitedCalc64_1; + mutable std::vector visitedCalc64_2; + mutable std::vector visitedCalc64_3; + mutable std::vector visitedCalc64_4; + mutable std::vector visitedCalc64_5; + mutable std::vector visitedCalc64_6; + mutable std::vector visitedCalc64_7; + + bool visitCalc64_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_3(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_4(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_5(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_6(const EventLabel *lab, View &calcRes) const; + bool visitCalc64_7(const EventLabel *lab, View &calcRes) const; + + View visitCalc64(const EventLabel *lab) const; + const View&getHbStableView(const EventLabel *lab) const { return lab->view(1); } + + auto checkCalc64(const EventLabel *lab) const; + mutable std::vector visitedCoherence_0; + mutable std::vector visitedCoherence_1; + mutable std::vector visitedCoherence_2; + mutable std::vector visitedCoherence_3; + mutable std::vector visitedCoherence_4; + mutable std::vector visitedCoherence_5; + mutable std::vector visitedCoherence_6; + mutable uint32_t visitedCoherenceAccepting; + + bool visitCoherence_0(const EventLabel *lab) const; + bool visitCoherence_1(const EventLabel *lab) const; + bool visitCoherence_2(const EventLabel *lab) const; + bool visitCoherence_3(const EventLabel *lab) const; + bool visitCoherence_4(const EventLabel *lab) const; + bool visitCoherence_5(const EventLabel *lab) const; + bool visitCoherence_6(const EventLabel *lab) const; + + bool visitCoherenceFull() const; + + mutable std::vector visitedConsAcyclic1_0; + mutable std::vector visitedConsAcyclic1_1; + mutable std::vector visitedConsAcyclic1_2; + mutable std::vector visitedConsAcyclic1_3; + mutable std::vector visitedConsAcyclic1_4; + mutable std::vector visitedConsAcyclic1_5; + mutable std::vector visitedConsAcyclic1_6; + mutable std::vector visitedConsAcyclic1_7; + mutable std::vector visitedConsAcyclic1_8; + mutable std::vector visitedConsAcyclic1_9; + mutable std::vector visitedConsAcyclic1_10; + mutable std::vector visitedConsAcyclic1_11; + mutable std::vector visitedConsAcyclic1_12; + mutable std::vector visitedConsAcyclic1_13; + mutable std::vector visitedConsAcyclic1_14; + mutable std::vector visitedConsAcyclic1_15; + mutable std::vector visitedConsAcyclic1_16; + mutable std::vector visitedConsAcyclic1_17; + mutable std::vector visitedConsAcyclic1_18; + mutable std::vector visitedConsAcyclic1_19; + mutable std::vector visitedConsAcyclic1_20; + mutable std::vector visitedConsAcyclic1_21; + mutable uint32_t visitedConsAcyclic1Accepting; + + bool visitConsAcyclic1_0(const EventLabel *lab) const; + bool visitConsAcyclic1_1(const EventLabel *lab) const; + bool visitConsAcyclic1_2(const EventLabel *lab) const; + bool visitConsAcyclic1_3(const EventLabel *lab) const; + bool visitConsAcyclic1_4(const EventLabel *lab) const; + bool visitConsAcyclic1_5(const EventLabel *lab) const; + bool visitConsAcyclic1_6(const EventLabel *lab) const; + bool visitConsAcyclic1_7(const EventLabel *lab) const; + bool visitConsAcyclic1_8(const EventLabel *lab) const; + bool visitConsAcyclic1_9(const EventLabel *lab) const; + bool visitConsAcyclic1_10(const EventLabel *lab) const; + bool visitConsAcyclic1_11(const EventLabel *lab) const; + bool visitConsAcyclic1_12(const EventLabel *lab) const; + bool visitConsAcyclic1_13(const EventLabel *lab) const; + bool visitConsAcyclic1_14(const EventLabel *lab) const; + bool visitConsAcyclic1_15(const EventLabel *lab) const; + bool visitConsAcyclic1_16(const EventLabel *lab) const; + bool visitConsAcyclic1_17(const EventLabel *lab) const; + bool visitConsAcyclic1_18(const EventLabel *lab) const; + bool visitConsAcyclic1_19(const EventLabel *lab) const; + bool visitConsAcyclic1_20(const EventLabel *lab) const; + bool visitConsAcyclic1_21(const EventLabel *lab) const; + + bool visitConsAcyclic1(const EventLabel *lab) const; + + bool visitConsAcyclic1Full() const; + + mutable std::vector visitedLHSUnlessConsAcyclic1_0; + mutable std::vector visitedLHSUnlessConsAcyclic1_1; + + bool visitLHSUnlessConsAcyclic1_0(const EventLabel *lab) const; + bool visitLHSUnlessConsAcyclic1_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessConsAcyclic1Accepting; + mutable std::vector visitedRHSUnlessConsAcyclic1Accepting; + bool visitUnlessConsAcyclic1(const EventLabel *lab) const; + bool checkConsAcyclic1(const EventLabel *lab) const; + bool visitError2(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError2_0; + mutable std::vector visitedLHSUnlessError2_1; + + bool visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError2Accepting; + bool visitUnlessError2(const EventLabel *lab) const; + bool checkError2(const EventLabel *lab) const; + bool visitError3(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError3_0; + mutable std::vector visitedLHSUnlessError3_1; + + bool visitLHSUnlessError3_0(const EventLabel *lab) const; + bool visitLHSUnlessError3_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError3Accepting; + mutable std::vector visitedRHSUnlessError3Accepting; + bool visitUnlessError3(const EventLabel *lab) const; + bool checkError3(const EventLabel *lab) const; + bool visitError4(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError4_0; + mutable std::vector visitedLHSUnlessError4_1; + mutable std::vector visitedLHSUnlessError4_2; + + bool visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError4Accepting; + bool visitUnlessError4(const EventLabel *lab) const; + bool checkError4(const EventLabel *lab) const; + bool visitError5(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError5_0; + mutable std::vector visitedLHSUnlessError5_1; + mutable std::vector visitedLHSUnlessError5_2; + + bool visitLHSUnlessError5_0(const EventLabel *lab) const; + bool visitLHSUnlessError5_1(const EventLabel *lab) const; + bool visitLHSUnlessError5_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError5Accepting; + mutable std::vector visitedRHSUnlessError5Accepting; + bool visitUnlessError5(const EventLabel *lab) const; + bool checkError5(const EventLabel *lab) const; + bool visitError6(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError6_0; + mutable std::vector visitedLHSUnlessError6_1; + mutable std::vector visitedLHSUnlessError6_2; + + bool visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError6Accepting; + bool visitUnlessError6(const EventLabel *lab) const; + bool checkError6(const EventLabel *lab) const; + bool visitError7(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError7_0; + mutable std::vector visitedLHSUnlessError7_1; + mutable std::vector visitedLHSUnlessError7_2; + + bool visitLHSUnlessError7_0(const EventLabel *lab) const; + bool visitLHSUnlessError7_1(const EventLabel *lab) const; + bool visitLHSUnlessError7_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError7Accepting; + mutable std::vector visitedRHSUnlessError7Accepting; + bool visitUnlessError7(const EventLabel *lab) const; + bool checkError7(const EventLabel *lab) const; + bool visitError8(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError8_0; + mutable std::vector visitedLHSUnlessError8_1; + + bool visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError8Accepting; + bool visitUnlessError8(const EventLabel *lab) const; + bool checkError8(const EventLabel *lab) const; + bool visitWarning9(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessWarning9_0; + mutable std::vector visitedLHSUnlessWarning9_1; + + bool visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessWarning9Accepting; + bool visitUnlessWarning9(const EventLabel *lab) const; + bool checkWarning9(const EventLabel *lab) const; + + void visitPPoRf0(const EventLabel *lab, View &pporf) const; + void visitPPoRf1(const EventLabel *lab, View &pporf) const; + + View calcPPoRfBefore(const EventLabel *lab) const; + + mutable std::vector visitedPPoRf0; + mutable std::vector visitedPPoRf1; + + +}; + +#endif /* GENMC_RC11_DRIVER_HPP */ diff --git a/src/RoundBoundDecider.cpp b/src/Verification/Consistency/RoundBoundDecider.cpp similarity index 96% rename from src/RoundBoundDecider.cpp rename to src/Verification/Consistency/RoundBoundDecider.cpp index 9bf0d7e..9691b81 100644 --- a/src/RoundBoundDecider.cpp +++ b/src/Verification/Consistency/RoundBoundDecider.cpp @@ -19,9 +19,9 @@ */ #include "RoundBoundDecider.hpp" -#include "ExecutionGraph.hpp" -#include "GraphIterators.hpp" -#include "View.hpp" +#include "ADT/View.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" auto areSCPredsInView(const ExecutionGraph &g, const View &v, Event e) -> bool { diff --git a/src/RoundBoundDecider.hpp b/src/Verification/Consistency/RoundBoundDecider.hpp similarity index 87% rename from src/RoundBoundDecider.hpp rename to src/Verification/Consistency/RoundBoundDecider.hpp index 5aee386..cca7969 100644 --- a/src/RoundBoundDecider.hpp +++ b/src/Verification/Consistency/RoundBoundDecider.hpp @@ -18,11 +18,11 @@ * Author: Iason Marmanis */ -#ifndef __ROUND_BOUND_DECIDER_HPP__ -#define __ROUND_BOUND_DECIDER_HPP__ +#ifndef GENMC_ROUND_BOUND_DECIDER_HPP +#define GENMC_ROUND_BOUND_DECIDER_HPP #include "BoundDecider.hpp" -#include "Event.hpp" +#include "ExecutionGraph/Event.hpp" class RoundBoundDecider : public BoundDecider { @@ -36,4 +36,4 @@ class RoundBoundDecider : public BoundDecider { #endif }; -#endif /* __ROUND_BOUND_DECIDER_HPP__ */ +#endif /* GENMC_ROUND_BOUND_DECIDER_HPP */ diff --git a/src/Verification/Consistency/SCDriver.cpp b/src/Verification/Consistency/SCDriver.cpp new file mode 100644 index 0000000..48522ed --- /dev/null +++ b/src/Verification/Consistency/SCDriver.cpp @@ -0,0 +1,1464 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#include "SCDriver.hpp" +#include "Static/ModuleInfo.hpp" + +SCDriver::SCDriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) + : GenMCDriver(conf, std::move(mod), std::move(MI), mode) {} + +bool SCDriver::isDepTracking() const +{ + return 0; +} + +bool SCDriver::visitCalc57_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool SCDriver::visitCalc57_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitCalc57_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc57_3(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitCalc57_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View SCDriver::visitCalc57(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc57_2(lab, calcRes); + return calcRes; +} +auto SCDriver::checkCalc57(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc57(lab); +} +bool SCDriver::visitCalc62_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool SCDriver::visitCalc62_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitCalc62_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc62_3(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitCalc62_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View SCDriver::visitCalc62(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc62_2(lab, calcRes); + return calcRes; +} +auto SCDriver::checkCalc62(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc62(lab); +} +void SCDriver::calculateSaved(EventLabel *lab) +{ +} + +void SCDriver::calculateViews(EventLabel *lab) +{ + lab->addView(checkCalc57(lab)); + lab->addView(checkCalc62(lab)); +} + +void SCDriver::updateMMViews(EventLabel *lab) +{ + calculateViews(lab); + calculateSaved(lab); + lab->setPrefixView(calculatePrefixView(lab)); +} + +const View &SCDriver::getHbView(const EventLabel *lab) const +{ + return lab->view(0); +} + + +bool SCDriver::isWriteRfBefore(Event a, Event b) +{ + auto &g = getGraph(); + auto &before = g.getEventLabel(b)->view(0); + if (before.contains(a)) + return true; + + const EventLabel *lab = g.getEventLabel(a); + + BUG_ON(!llvm::isa(lab)); + auto *wLab = static_cast(lab); + for (auto &rLab : wLab->readers()) + if (before.contains(rLab.getPos())) + return true; + return false; +} + +std::vector +SCDriver::getInitRfsAtLoc(SAddr addr) +{ + std::vector result; + + for (const auto &lab : getGraph().labels()) { + if (auto *rLab = llvm::dyn_cast(&lab)) + if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) + result.push_back(rLab->getPos()); + } + return result; +} + +bool SCDriver::isHbOptRfBefore(const Event e, const Event write) +{ + auto &g = getGraph(); + const EventLabel *lab = g.getEventLabel(write); + + BUG_ON(!llvm::isa(lab)); + auto *sLab = static_cast(lab); + if (sLab->view(0).contains(e)) + return true; + + for (auto &rLab : sLab->readers()) { + if (rLab.view(0).contains(e)) + return true; + } + return false; +} + +ExecutionGraph::co_iterator +SCDriver::splitLocMOBefore(SAddr addr, Event e) +{ + auto &g = getGraph(); + auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), [&](auto &lab){ + return isWriteRfBefore(lab.getPos(), e); + }); + /* Convert to forward iterator, but be _really_ careful */ + if (rit == g.co_rend(addr)) + return g.co_begin(addr); + return ++ExecutionGraph::co_iterator(*rit); +} + +ExecutionGraph::co_iterator +SCDriver::splitLocMOAfterHb(SAddr addr, const Event read) +{ + auto &g = getGraph(); + + auto initRfs = g.getInitRfsAtLoc(addr); + if (std::any_of(initRfs.begin(), initRfs.end(), [&read,&g](const Event &rf){ + return g.getEventLabel(rf)->view(0).contains(read); + })) + return g.co_begin(addr); + + auto it = std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(read, lab.getPos()); + }); + if (it == g.co_end(addr) || it->view(0).contains(read)) + return it; + return ++it; +} + +ExecutionGraph::co_iterator +SCDriver::splitLocMOAfter(SAddr addr, const Event e) +{ + auto &g = getGraph(); + return std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(e, lab.getPos()); + }); +} + +std::vector +SCDriver::getCoherentStores(SAddr addr, Event read) +{ + auto &g = getGraph(); + std::vector stores; + + /* Fastpath: co_max(G) is po-before R */ + auto comax = g.co_rbegin(addr) == g.co_rend(addr) ? Event::getInit() : + g.co_rbegin(addr)->getPos(); + if (comax.thread == read.thread && comax.index < read.index) + return {comax}; + + /* + * If there are no stores (rf?;hb)-before the current event + * then we can read read from all concurrent stores and the + * initializer store. Otherwise, we can read from all concurrent + * stores and the mo-latest of the (rf?;hb)-before stores. + */ + auto begIt = splitLocMOBefore(addr, read); + if (begIt == g.co_begin(addr)) + stores.push_back(Event::getInit()); + else { + stores.push_back((--begIt)->getPos()); + ++begIt; + } + + /* + * If the model supports out-of-order execution we have to also + * account for the possibility the read is hb-before some other + * store, or some read that reads from a store. + */ + auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); + std::transform(begIt, endIt, std::back_inserter(stores), [&](auto &lab){ + return lab.getPos(); + }); + return stores; +} + +std::vector +SCDriver::getMOOptRfAfter(const WriteLabel *sLab) +{ + std::vector after; + std::vector rfAfter; + + const auto &g = getGraph(); + std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), + [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + return after; +} + +std::vector +SCDriver::getMOInvOptRfAfter(const WriteLabel *sLab) +{ + auto &g = getGraph(); + std::vector after; + std::vector rfAfter; + + /* First, add (mo;rf?)-before */ + std::for_each(g.co_pred_begin(sLab), + g.co_pred_end(sLab), [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + + /* Then, we add the reader list for the initializer */ + auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); + after.insert(after.end(), initRfs.begin(), initRfs.end()); + return after; +} + +static std::vector +getRevisitableFrom(const ExecutionGraph &g, const WriteLabel *sLab, + const VectorClock &pporf, const WriteLabel *coPred) +{ + auto pendingRMW = g.getPendingRMW(sLab); + std::vector loads; + + for (auto &rLab : coPred->readers()) { + if (!pporf.contains(rLab.getPos()) && rLab.getAddr() == sLab->getAddr() && + rLab.isRevisitable() && rLab.wasAddedMax()) + loads.push_back(rLab.getPos()); + } + if (!pendingRMW.isInitializer()) + loads.erase(std::remove_if(loads.begin(), loads.end(), + [&](Event &e) { + auto *confLab = g.getEventLabel(pendingRMW); + return g.getEventLabel(e)->getStamp() > + confLab->getStamp(); + }), + loads.end()); + return loads; +} + +std::vector +SCDriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) +{ + auto &g = getGraph(); + std::vector ls; + + /* Fastpath: previous co-max is ppo-before SLAB */ + auto prevCoMaxIt = std::find_if(g.co_rbegin(sLab->getAddr()), g.co_rend(sLab->getAddr()), + [&](auto &lab) { return lab.getPos() != sLab->getPos(); }); + if (prevCoMaxIt != g.co_rend(sLab->getAddr()) && pporf.contains(prevCoMaxIt->getPos())) { + ls = getRevisitableFrom(g, sLab, pporf, &*prevCoMaxIt); + } else { + ls = g.getRevisitable(sLab, pporf); + } + + /* If this store is po- and mo-maximal then we are done */ + if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) + return ls; + + /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ + auto optRfs = getMOOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { const View &before = g.getEventLabel(e)->view(0); + return std::any_of(optRfs.begin(), optRfs.end(), + [&](Event ev) + { return before.contains(ev); }); + }), ls.end()); + + /* If out-of-order event addition is not supported, then we are done + * due to po-maximality */ + if (!isDepTracking()) + return ls; + + /* Otherwise, we also have to exclude hb-before loads */ + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { return g.getEventLabel(sLab->getPos())->view(0).contains(e); }), + ls.end()); + + /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in + * the resulting graph */ + auto &before = pporf; + auto moInvOptRfs = getMOInvOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { auto *eLab = g.getEventLabel(e); + auto v = g.getViewFromStamp(eLab->getStamp()); + v->update(before); + return std::any_of(moInvOptRfs.begin(), + moInvOptRfs.end(), + [&](Event ev) + { return v->contains(ev) && + g.getEventLabel(ev)->view(0).contains(e); }); + }), + ls.end()); + + return ls; +} + +std::vector +SCDriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) +{ + auto &g = getGraph(); + std::vector result; + + /* If it is an RMW store, there is only one possible position in MO */ + if (isRMW) { + auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev())); + BUG_ON(!rLab); + auto *rfLab = rLab->getRf(); + BUG_ON(!rfLab); + result.push_back(rfLab->getPos()); + return result; + } + + /* Otherwise, we calculate the full range and add the store */ + auto rangeBegin = splitLocMOBefore(addr, store); + auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); + auto cos = llvm::iterator_range(rangeBegin, rangeEnd) | + std::views::filter([&](auto &sLab) { return !g.isRMWStore(sLab.getPos()); }) | + std::views::transform([&](auto &sLab) { + auto *pLab = g.co_imm_pred(&sLab); + return pLab ? pLab->getPos() : Event::getInit(); + }); + std::ranges::copy(cos, std::back_inserter(result)); + result.push_back(rangeEnd == g.co_end(addr) ? g.co_max(addr)->getPos() + : !g.co_imm_pred(&*rangeEnd) ? Event::getInit() + : g.co_imm_pred(&*rangeEnd)->getPos()); + return result; +} +bool SCDriver::visitCoherence_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedCoherenceAccepting; + + + --visitedCoherenceAccepting; + return true; +} + +bool SCDriver::visitCoherence_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_2(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool SCDriver::visitCoherence_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + return true; +} + +bool SCDriver::visitCoherenceFull() const +{ + auto &g = getGraph(); + + visitedCoherenceAccepting = 0; + visitedCoherence_1.clear(); + visitedCoherence_1.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedCoherence_1[lab.getStamp().get()].status != NodeStatus::unseen || visitCoherence_1(&lab); }); +} + +bool SCDriver::visitConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedConsAcyclic1Accepting; + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + + if (auto pLab = tc_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rf_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + --visitedConsAcyclic1Accepting; + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool SCDriver::visitConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + return true + && (visitedConsAcyclic1_0[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_0(lab)); +} + +bool SCDriver::visitConsAcyclic1Full() const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedConsAcyclic1_0[lab.getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_0(&lab); }); +} + +bool SCDriver::checkConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return visitConsAcyclic1(lab); +} +bool SCDriver::visitError2(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool SCDriver::visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError2_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError2Accepting.clear(); + visitedLHSUnlessError2Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError2_1(lab, v); +} + +bool SCDriver::checkError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError2(lab)) + return true; + + return visitError2(lab); +} +bool SCDriver::visitError3(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError3_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool SCDriver::visitLHSUnlessError3_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError3Accepting.clear(); + visitedLHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError3Accepting.clear(); + visitedRHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError3_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError3Accepting.size(); i++) { + if (visitedLHSUnlessError3Accepting[i] && !visitedRHSUnlessError3Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool SCDriver::checkError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError3(lab)) + return true; + + return visitError3(lab); +} +bool SCDriver::visitError4(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool SCDriver::visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_1(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError4Accepting.clear(); + visitedLHSUnlessError4Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError4_2(lab, v); +} + +bool SCDriver::checkError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError4(lab)) + return true; + + return visitError4(lab); +} +bool SCDriver::visitError5(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError5_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool SCDriver::visitLHSUnlessError5_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError5_0(pLab)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitLHSUnlessError5_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError5_1(pLab)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError5Accepting.clear(); + visitedLHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError5Accepting.clear(); + visitedRHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError5_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError5Accepting.size(); i++) { + if (visitedLHSUnlessError5Accepting[i] && !visitedRHSUnlessError5Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool SCDriver::checkError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError5(lab)) + return true; + + return visitError5(lab); +} +bool SCDriver::visitError6(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool SCDriver::visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError6_1(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError6Accepting.clear(); + visitedLHSUnlessError6Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError6_2(lab, v); +} + +bool SCDriver::checkError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError6(lab)) + return true; + + return visitError6(lab); +} +bool SCDriver::visitError7(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError7_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool SCDriver::visitLHSUnlessError7_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitLHSUnlessError7_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && llvm::dyn_cast(lab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(lab)))if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError7_1(pLab)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError7Accepting.clear(); + visitedLHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError7Accepting.clear(); + visitedRHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError7_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError7Accepting.size(); i++) { + if (visitedLHSUnlessError7Accepting[i] && !visitedRHSUnlessError7Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool SCDriver::checkError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError7(lab)) + return true; + + return visitError7(lab); +} +bool SCDriver::visitError8(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool SCDriver::visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError8Accepting.clear(); + visitedLHSUnlessError8Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError8_1(lab, v); +} + +bool SCDriver::checkError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError8(lab)) + return true; + + return visitError8(lab); +} +bool SCDriver::visitWarning9(const EventLabel *lab) const +{ + return false; +} + +bool SCDriver::visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool SCDriver::visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessWarning9_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool SCDriver::visitUnlessWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessWarning9Accepting.clear(); + visitedLHSUnlessWarning9Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessWarning9_1(lab, v); +} + +bool SCDriver::checkWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessWarning9(lab)) + return true; + + return visitWarning9(lab); +} +VerificationError SCDriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const +{ + if (!checkError2(lab)) { + race = cexLab; + return VerificationError::VE_AccessNonMalloc; + } + + if (!checkError3(lab)) { + race = cexLab; + return VerificationError::VE_DoubleFree; + } + + if (!checkError4(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError5(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError6(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError7(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError8(lab)) { + race = cexLab; + return VerificationError::VE_RaceNotAtomic; + } + + return VerificationError::VE_OK; +} + +std::vector SCDriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const +{ + std::vector result; + + if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkWarning9(lab)) { + racyLabs.push_back(cexLab); + result.push_back(VerificationError::VE_WWRace); + } + + return result; +} + +bool SCDriver::isConsistent(const EventLabel *lab) const +{ + + return true + && checkConsAcyclic1(lab); +} + +View SCDriver::calcPPoRfBefore(const EventLabel *lab) const +{ + auto &g = getGraph(); + View pporf; + pporf.updateIdx(lab->getPos()); + + auto *pLab = g.getPreviousLabel(lab); + if (!pLab) + return pporf; + pporf.update(pLab->getPrefixView()); + if (auto *rLab = llvm::dyn_cast(pLab)) + pporf.update(rLab->getRf()->getPrefixView()); + if (auto *tsLab = llvm::dyn_cast(pLab)) + pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); + if (auto *tjLab = llvm::dyn_cast(pLab)) + pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); + return pporf; +} +std::unique_ptr SCDriver::calculatePrefixView(const EventLabel *lab) const +{ + return std::make_unique(calcPPoRfBefore(lab)); +} diff --git a/src/Verification/Consistency/SCDriver.hpp b/src/Verification/Consistency/SCDriver.hpp new file mode 100644 index 0000000..f89a5e1 --- /dev/null +++ b/src/Verification/Consistency/SCDriver.hpp @@ -0,0 +1,237 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#ifndef GENMC_SC_DRIVER_HPP +#define GENMC_SC_DRIVER_HPP + +#include "config.h" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Verification/GenMCDriver.hpp" +#include "Verification/VerificationError.hpp" +#include +#include + +class SCDriver : public GenMCDriver { + +private: + enum class NodeStatus : unsigned char { unseen, entered, left }; + + struct NodeVisitStatus { + NodeVisitStatus() = default; + NodeVisitStatus(uint32_t c, NodeStatus s) : count(c), status(s) {} + uint32_t count{}; + NodeStatus status{}; + }; + +public: + SCDriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); + + void calculateSaved(EventLabel *lab); + void calculateViews(EventLabel *lab); + void updateMMViews(EventLabel *lab) override; + bool isDepTracking() const override; + bool isConsistent(const EventLabel *lab) const override; + VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const override; + std::vector checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const; + std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; + const View &getHbView(const EventLabel *lab) const override; + std::vector getCoherentStores(SAddr addr, Event read) override; + std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) override; + std::vector getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; + +private: + bool isWriteRfBefore(Event a, Event b); + std::vector getInitRfsAtLoc(SAddr addr); + bool isHbOptRfBefore(const Event e, const Event write); + ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); + ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); + ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); + std::vector getMOOptRfAfter(const WriteLabel *sLab); + std::vector getMOInvOptRfAfter(const WriteLabel *sLab); + mutable const EventLabel *cexLab{}; + + mutable std::vector visitedCalc57_0; + mutable std::vector visitedCalc57_1; + mutable std::vector visitedCalc57_2; + mutable std::vector visitedCalc57_3; + + bool visitCalc57_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc57(const EventLabel *lab) const; + const View&getHbStableView(const EventLabel *lab) const { return lab->view(0); } + + auto checkCalc57(const EventLabel *lab) const; + mutable std::vector visitedCalc62_0; + mutable std::vector visitedCalc62_1; + mutable std::vector visitedCalc62_2; + mutable std::vector visitedCalc62_3; + + bool visitCalc62_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc62(const EventLabel *lab) const; + const View&getPorfStableView(const EventLabel *lab) const { return lab->view(1); } + + auto checkCalc62(const EventLabel *lab) const; + mutable std::vector visitedCoherence_0; + mutable std::vector visitedCoherence_1; + mutable std::vector visitedCoherence_2; + mutable uint32_t visitedCoherenceAccepting; + + bool visitCoherence_0(const EventLabel *lab) const; + bool visitCoherence_1(const EventLabel *lab) const; + bool visitCoherence_2(const EventLabel *lab) const; + + bool visitCoherenceFull() const; + + mutable std::vector visitedConsAcyclic1_0; + mutable uint32_t visitedConsAcyclic1Accepting; + + bool visitConsAcyclic1_0(const EventLabel *lab) const; + + bool visitConsAcyclic1(const EventLabel *lab) const; + + bool visitConsAcyclic1Full() const; + + bool checkUnlessConsAcyclic1(const EventLabel *lab) { return false; } + bool checkConsAcyclic1(const EventLabel *lab) const; + bool visitError2(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError2_0; + mutable std::vector visitedLHSUnlessError2_1; + + bool visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError2Accepting; + bool visitUnlessError2(const EventLabel *lab) const; + bool checkError2(const EventLabel *lab) const; + bool visitError3(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError3_0; + mutable std::vector visitedLHSUnlessError3_1; + + bool visitLHSUnlessError3_0(const EventLabel *lab) const; + bool visitLHSUnlessError3_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError3Accepting; + mutable std::vector visitedRHSUnlessError3Accepting; + bool visitUnlessError3(const EventLabel *lab) const; + bool checkError3(const EventLabel *lab) const; + bool visitError4(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError4_0; + mutable std::vector visitedLHSUnlessError4_1; + mutable std::vector visitedLHSUnlessError4_2; + + bool visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError4Accepting; + bool visitUnlessError4(const EventLabel *lab) const; + bool checkError4(const EventLabel *lab) const; + bool visitError5(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError5_0; + mutable std::vector visitedLHSUnlessError5_1; + mutable std::vector visitedLHSUnlessError5_2; + + bool visitLHSUnlessError5_0(const EventLabel *lab) const; + bool visitLHSUnlessError5_1(const EventLabel *lab) const; + bool visitLHSUnlessError5_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError5Accepting; + mutable std::vector visitedRHSUnlessError5Accepting; + bool visitUnlessError5(const EventLabel *lab) const; + bool checkError5(const EventLabel *lab) const; + bool visitError6(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError6_0; + mutable std::vector visitedLHSUnlessError6_1; + mutable std::vector visitedLHSUnlessError6_2; + + bool visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError6Accepting; + bool visitUnlessError6(const EventLabel *lab) const; + bool checkError6(const EventLabel *lab) const; + bool visitError7(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError7_0; + mutable std::vector visitedLHSUnlessError7_1; + mutable std::vector visitedLHSUnlessError7_2; + + bool visitLHSUnlessError7_0(const EventLabel *lab) const; + bool visitLHSUnlessError7_1(const EventLabel *lab) const; + bool visitLHSUnlessError7_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError7Accepting; + mutable std::vector visitedRHSUnlessError7Accepting; + bool visitUnlessError7(const EventLabel *lab) const; + bool checkError7(const EventLabel *lab) const; + bool visitError8(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError8_0; + mutable std::vector visitedLHSUnlessError8_1; + + bool visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError8Accepting; + bool visitUnlessError8(const EventLabel *lab) const; + bool checkError8(const EventLabel *lab) const; + bool visitWarning9(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessWarning9_0; + mutable std::vector visitedLHSUnlessWarning9_1; + + bool visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessWarning9Accepting; + bool visitUnlessWarning9(const EventLabel *lab) const; + bool checkWarning9(const EventLabel *lab) const; + + void visitPPoRf0(const EventLabel *lab, View &pporf) const; + void visitPPoRf1(const EventLabel *lab, View &pporf) const; + + View calcPPoRfBefore(const EventLabel *lab) const; + + mutable std::vector visitedPPoRf0; + mutable std::vector visitedPPoRf1; + + +}; + +#endif /* GENMC_SC_DRIVER_HPP */ diff --git a/src/Verification/Consistency/TSODriver.cpp b/src/Verification/Consistency/TSODriver.cpp new file mode 100644 index 0000000..4107d6e --- /dev/null +++ b/src/Verification/Consistency/TSODriver.cpp @@ -0,0 +1,1805 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#include "TSODriver.hpp" +#include "Static/ModuleInfo.hpp" + +TSODriver::TSODriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode /* = GenMCDriver::VerificationMode{} */) + : GenMCDriver(conf, std::move(mod), std::move(MI), mode) {} + +bool TSODriver::isDepTracking() const +{ + return 0; +} + +bool TSODriver::visitCalc57_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool TSODriver::visitCalc57_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(0)); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitCalc57_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitCalc57_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc57_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc57_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc57_2(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View TSODriver::visitCalc57(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc57_3(lab, calcRes); + return calcRes; +} +auto TSODriver::checkCalc57(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc57(lab); +} +bool TSODriver::visitCalc62_0(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + + + return true; +} + +bool TSODriver::visitCalc62_1(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = lab; true)if (calcRes.update(pLab->view(1)); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitCalc62_2(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc62_3(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitCalc62_3(const EventLabel *lab, View &calcRes) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab)if (calcRes.updateIdx(pLab->getPos()); true) { + if (!visitCalc62_0(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCalc62_1(pLab, calcRes)){ + return false; + } + + } + + return true; +} + +View TSODriver::visitCalc62(const EventLabel *lab) const +{ + auto &g = getGraph(); + View calcRes; + + + visitCalc62_2(lab, calcRes); + return calcRes; +} +auto TSODriver::checkCalc62(const EventLabel *lab) const +{ + auto &g = getGraph(); + + return visitCalc62(lab); +} +void TSODriver::calculateSaved(EventLabel *lab) +{ +} + +void TSODriver::calculateViews(EventLabel *lab) +{ + lab->addView(checkCalc57(lab)); + lab->addView(checkCalc62(lab)); +} + +void TSODriver::updateMMViews(EventLabel *lab) +{ + calculateViews(lab); + calculateSaved(lab); + lab->setPrefixView(calculatePrefixView(lab)); +} + +const View &TSODriver::getHbView(const EventLabel *lab) const +{ + return lab->view(0); +} + + +bool TSODriver::isWriteRfBefore(Event a, Event b) +{ + auto &g = getGraph(); + auto &before = g.getEventLabel(b)->view(0); + if (before.contains(a)) + return true; + + const EventLabel *lab = g.getEventLabel(a); + + BUG_ON(!llvm::isa(lab)); + auto *wLab = static_cast(lab); + for (auto &rLab : wLab->readers()) + if (before.contains(rLab.getPos())) + return true; + return false; +} + +std::vector +TSODriver::getInitRfsAtLoc(SAddr addr) +{ + std::vector result; + + for (const auto &lab : getGraph().labels()) { + if (auto *rLab = llvm::dyn_cast(&lab)) + if (rLab->getRf()->getPos().isInitializer() && rLab->getAddr() == addr) + result.push_back(rLab->getPos()); + } + return result; +} + +bool TSODriver::isHbOptRfBefore(const Event e, const Event write) +{ + auto &g = getGraph(); + const EventLabel *lab = g.getEventLabel(write); + + BUG_ON(!llvm::isa(lab)); + auto *sLab = static_cast(lab); + if (sLab->view(0).contains(e)) + return true; + + for (auto &rLab : sLab->readers()) { + if (rLab.view(0).contains(e)) + return true; + } + return false; +} + +ExecutionGraph::co_iterator +TSODriver::splitLocMOBefore(SAddr addr, Event e) +{ + auto &g = getGraph(); + auto rit = std::find_if(g.co_rbegin(addr), g.co_rend(addr), [&](auto &lab){ + return isWriteRfBefore(lab.getPos(), e); + }); + /* Convert to forward iterator, but be _really_ careful */ + if (rit == g.co_rend(addr)) + return g.co_begin(addr); + return ++ExecutionGraph::co_iterator(*rit); +} + +ExecutionGraph::co_iterator +TSODriver::splitLocMOAfterHb(SAddr addr, const Event read) +{ + auto &g = getGraph(); + + auto initRfs = g.getInitRfsAtLoc(addr); + if (std::any_of(initRfs.begin(), initRfs.end(), [&read,&g](const Event &rf){ + return g.getEventLabel(rf)->view(0).contains(read); + })) + return g.co_begin(addr); + + auto it = std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(read, lab.getPos()); + }); + if (it == g.co_end(addr) || it->view(0).contains(read)) + return it; + return ++it; +} + +ExecutionGraph::co_iterator +TSODriver::splitLocMOAfter(SAddr addr, const Event e) +{ + auto &g = getGraph(); + return std::find_if(g.co_begin(addr), g.co_end(addr), [&](auto &lab){ + return isHbOptRfBefore(e, lab.getPos()); + }); +} + +std::vector +TSODriver::getCoherentStores(SAddr addr, Event read) +{ + auto &g = getGraph(); + std::vector stores; + + /* Fastpath: co_max(G) is po-before R */ + auto comax = g.co_rbegin(addr) == g.co_rend(addr) ? Event::getInit() : + g.co_rbegin(addr)->getPos(); + if (comax.thread == read.thread && comax.index < read.index) + return {comax}; + + /* + * If there are no stores (rf?;hb)-before the current event + * then we can read read from all concurrent stores and the + * initializer store. Otherwise, we can read from all concurrent + * stores and the mo-latest of the (rf?;hb)-before stores. + */ + auto begIt = splitLocMOBefore(addr, read); + if (begIt == g.co_begin(addr)) + stores.push_back(Event::getInit()); + else { + stores.push_back((--begIt)->getPos()); + ++begIt; + } + + /* + * If the model supports out-of-order execution we have to also + * account for the possibility the read is hb-before some other + * store, or some read that reads from a store. + */ + auto endIt = (isDepTracking()) ? splitLocMOAfterHb(addr, read) : g.co_end(addr); + std::transform(begIt, endIt, std::back_inserter(stores), [&](auto &lab){ + return lab.getPos(); + }); + return stores; +} + +std::vector +TSODriver::getMOOptRfAfter(const WriteLabel *sLab) +{ + std::vector after; + std::vector rfAfter; + + const auto &g = getGraph(); + std::for_each(g.co_succ_begin(sLab), g.co_succ_end(sLab), + [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + return after; +} + +std::vector +TSODriver::getMOInvOptRfAfter(const WriteLabel *sLab) +{ + auto &g = getGraph(); + std::vector after; + std::vector rfAfter; + + /* First, add (mo;rf?)-before */ + std::for_each(g.co_pred_begin(sLab), + g.co_pred_end(sLab), [&](auto &wLab){ + after.push_back(wLab.getPos()); + std::transform(wLab.readers_begin(), wLab.readers_end(), std::back_inserter(rfAfter), + [&](auto &rLab){ return &rLab; }); + }); + std::transform(rfAfter.begin(), rfAfter.end(), std::back_inserter(after), [](auto *rLab){ + return rLab->getPos(); + }); + + /* Then, we add the reader list for the initializer */ + auto initRfs = g.getInitRfsAtLoc(sLab->getAddr()); + after.insert(after.end(), initRfs.begin(), initRfs.end()); + return after; +} + +static std::vector +getRevisitableFrom(const ExecutionGraph &g, const WriteLabel *sLab, + const VectorClock &pporf, const WriteLabel *coPred) +{ + auto pendingRMW = g.getPendingRMW(sLab); + std::vector loads; + + for (auto &rLab : coPred->readers()) { + if (!pporf.contains(rLab.getPos()) && rLab.getAddr() == sLab->getAddr() && + rLab.isRevisitable() && rLab.wasAddedMax()) + loads.push_back(rLab.getPos()); + } + if (!pendingRMW.isInitializer()) + loads.erase(std::remove_if(loads.begin(), loads.end(), + [&](Event &e) { + auto *confLab = g.getEventLabel(pendingRMW); + return g.getEventLabel(e)->getStamp() > + confLab->getStamp(); + }), + loads.end()); + return loads; +} + +std::vector +TSODriver::getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) +{ + auto &g = getGraph(); + std::vector ls; + + /* Fastpath: previous co-max is ppo-before SLAB */ + auto prevCoMaxIt = std::find_if(g.co_rbegin(sLab->getAddr()), g.co_rend(sLab->getAddr()), + [&](auto &lab) { return lab.getPos() != sLab->getPos(); }); + if (prevCoMaxIt != g.co_rend(sLab->getAddr()) && pporf.contains(prevCoMaxIt->getPos())) { + ls = getRevisitableFrom(g, sLab, pporf, &*prevCoMaxIt); + } else { + ls = g.getRevisitable(sLab, pporf); + } + + /* If this store is po- and mo-maximal then we are done */ + if (!isDepTracking() && g.isCoMaximal(sLab->getAddr(), sLab->getPos())) + return ls; + + /* First, we have to exclude (mo;rf?;hb?;sb)-after reads */ + auto optRfs = getMOOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { const View &before = g.getEventLabel(e)->view(0); + return std::any_of(optRfs.begin(), optRfs.end(), + [&](Event ev) + { return before.contains(ev); }); + }), ls.end()); + + /* If out-of-order event addition is not supported, then we are done + * due to po-maximality */ + if (!isDepTracking()) + return ls; + + /* Otherwise, we also have to exclude hb-before loads */ + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { return g.getEventLabel(sLab->getPos())->view(0).contains(e); }), + ls.end()); + + /* ...and also exclude (mo^-1; rf?; (hb^-1)?; sb^-1)-after reads in + * the resulting graph */ + auto &before = pporf; + auto moInvOptRfs = getMOInvOptRfAfter(sLab); + ls.erase(std::remove_if(ls.begin(), ls.end(), [&](Event e) + { auto *eLab = g.getEventLabel(e); + auto v = g.getViewFromStamp(eLab->getStamp()); + v->update(before); + return std::any_of(moInvOptRfs.begin(), + moInvOptRfs.end(), + [&](Event ev) + { return v->contains(ev) && + g.getEventLabel(ev)->view(0).contains(e); }); + }), + ls.end()); + + return ls; +} + +std::vector +TSODriver::getCoherentPlacings(SAddr addr, Event store, bool isRMW) +{ + auto &g = getGraph(); + std::vector result; + + /* If it is an RMW store, there is only one possible position in MO */ + if (isRMW) { + auto *rLab = llvm::dyn_cast(g.getEventLabel(store.prev())); + BUG_ON(!rLab); + auto *rfLab = rLab->getRf(); + BUG_ON(!rfLab); + result.push_back(rfLab->getPos()); + return result; + } + + /* Otherwise, we calculate the full range and add the store */ + auto rangeBegin = splitLocMOBefore(addr, store); + auto rangeEnd = (isDepTracking()) ? splitLocMOAfter(addr, store) : g.co_end(addr); + auto cos = llvm::iterator_range(rangeBegin, rangeEnd) | + std::views::filter([&](auto &sLab) { return !g.isRMWStore(sLab.getPos()); }) | + std::views::transform([&](auto &sLab) { + auto *pLab = g.co_imm_pred(&sLab); + return pLab ? pLab->getPos() : Event::getInit(); + }); + std::ranges::copy(cos, std::back_inserter(result)); + result.push_back(rangeEnd == g.co_end(addr) ? g.co_max(addr)->getPos() + : !g.co_imm_pred(&*rangeEnd) ? Event::getInit() + : g.co_imm_pred(&*rangeEnd)->getPos()); + return result; +} +bool TSODriver::visitCoherence_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedCoherenceAccepting; + + + --visitedCoherenceAccepting; + return true; +} + +bool TSODriver::visitCoherence_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::entered }; + + if (auto pLab = po_imm_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_2(pLab)){ + return false; + } + } + if (auto pLab = po_imm_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + visitedCoherence_1[lab->getStamp().get()] = { visitedCoherenceAccepting, NodeStatus::left }; + return true; +} + +bool TSODriver::visitCoherence_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = tc_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + auto &node = visitedCoherence_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitCoherence_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedCoherenceAccepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = tc_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = tj_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + if (auto pLab = rf_pred(g, lab); pLab) { + if (!visitCoherence_0(pLab)){ + return false; + } + } + return true; +} + +bool TSODriver::visitCoherenceFull() const +{ + auto &g = getGraph(); + + visitedCoherenceAccepting = 0; + visitedCoherence_1.clear(); + visitedCoherence_1.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedCoherence_1[lab.getStamp().get()].status != NodeStatus::unseen || visitCoherence_1(&lab); }); +} + +bool TSODriver::visitConsAcyclic1_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_0[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool TSODriver::visitConsAcyclic1_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_1[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool TSODriver::visitConsAcyclic1_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + visitedConsAcyclic1_2[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool TSODriver::visitConsAcyclic1_3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + ++visitedConsAcyclic1Accepting; + visitedConsAcyclic1_3[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::entered }; + + + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_2[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_2(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = co_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = fr_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + for (auto &tmp : rfe_succs(g, lab)) if (auto *pLab = &tmp; true) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && lab->isSC() && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab)if (true && pLab->isSC() && llvm::isa(pLab)) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_3[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_3(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 1)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab) && ((llvm::isa(lab) && g.isRMWLoad(lab)) || (llvm::isa(lab) && g.isRMWStore(lab))))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (true && llvm::isa(lab))if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_0[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_0(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + if (auto pLab = po_imm_succ(g, lab); pLab) { + auto &node = visitedConsAcyclic1_1[pLab->getStamp().get()]; + if (node.status == NodeStatus::unseen) { + if (!visitConsAcyclic1_1(pLab)){ + return false; + } + } else if (node.status == NodeStatus::entered && (visitedConsAcyclic1Accepting > node.count || 0)) { + + return false; + } else if (node.status == NodeStatus::left) { + + } + } + --visitedConsAcyclic1Accepting; + visitedConsAcyclic1_3[lab->getStamp().get()] = { visitedConsAcyclic1Accepting, NodeStatus::left }; + return true; +} + +bool TSODriver::visitConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_3.clear(); + visitedConsAcyclic1_3.resize(g.getMaxStamp().get() + 1); + return true + && (visitedConsAcyclic1_3[lab->getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_3(lab)); +} + +bool TSODriver::visitConsAcyclic1Full() const +{ + auto &g = getGraph(); + + visitedConsAcyclic1Accepting = 0; + visitedConsAcyclic1_0.clear(); + visitedConsAcyclic1_0.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_1.clear(); + visitedConsAcyclic1_1.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_2.clear(); + visitedConsAcyclic1_2.resize(g.getMaxStamp().get() + 1); + visitedConsAcyclic1_3.clear(); + visitedConsAcyclic1_3.resize(g.getMaxStamp().get() + 1); + return true + && std::ranges::all_of(g.labels(), [&](auto &lab){ return visitedConsAcyclic1_3[lab.getStamp().get()].status != NodeStatus::unseen || visitConsAcyclic1_3(&lab); }); +} + +bool TSODriver::checkConsAcyclic1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return visitConsAcyclic1(lab); +} +bool TSODriver::visitError2(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool TSODriver::visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError2_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError2Accepting.clear(); + visitedLHSUnlessError2Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError2_1(lab, v); +} + +bool TSODriver::checkError2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError2(lab)) + return true; + + return visitError2(lab); +} +bool TSODriver::visitError3(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError3_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool TSODriver::visitLHSUnlessError3_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError3_0(pLab)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError3Accepting.clear(); + visitedLHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError3Accepting.clear(); + visitedRHSUnlessError3Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError3_1(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError3Accepting.size(); i++) { + if (visitedLHSUnlessError3Accepting[i] && !visitedRHSUnlessError3Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool TSODriver::checkError3(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError3(lab)) + return true; + + return visitError3(lab); +} +bool TSODriver::visitError4(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool TSODriver::visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab) && !llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError4_1(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError4Accepting.clear(); + visitedLHSUnlessError4Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError4_2(lab, v); +} + +bool TSODriver::checkError4(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError4(lab)) + return true; + + return visitError4(lab); +} +bool TSODriver::visitError5(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError5_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool TSODriver::visitLHSUnlessError5_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab) && !llvm::isa(pLab)) { + if (!visitLHSUnlessError5_0(pLab)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitLHSUnlessError5_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError5_1(pLab)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError5Accepting.clear(); + visitedLHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError5Accepting.clear(); + visitedRHSUnlessError5Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError5_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError5Accepting.size(); i++) { + if (visitedLHSUnlessError5Accepting[i] && !visitedRHSUnlessError5Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool TSODriver::checkError5(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError5(lab)) + return true; + + return visitError5(lab); +} +bool TSODriver::visitError6(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool TSODriver::visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + for (auto &tmp : alloc_succs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab)if (true && llvm::isa(pLab) && llvm::dyn_cast(pLab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(pLab))) { + if (!visitLHSUnlessError6_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))if (auto pLab = free_pred(g, lab); pLab) { + if (!visitLHSUnlessError6_1(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError6Accepting.clear(); + visitedLHSUnlessError6Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError6_2(lab, v); +} + +bool TSODriver::checkError6(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError6(lab)) + return true; + + return visitError6(lab); +} +bool TSODriver::visitError7(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError7_0(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + return false; + + + return true; +} + +bool TSODriver::visitLHSUnlessError7_1(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (auto pLab = free_succ(g, lab); pLab)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError7_0(pLab)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitLHSUnlessError7_2(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab) && llvm::dyn_cast(lab)->getAddr().isDynamic() && !isHazptrProtected(llvm::dyn_cast(lab)))if (auto pLab = alloc_pred(g, lab); pLab) { + if (!visitLHSUnlessError7_1(pLab)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError7Accepting.clear(); + visitedLHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + visitedRHSUnlessError7Accepting.clear(); + visitedRHSUnlessError7Accepting.resize(g.getMaxStamp().get() + 1, false); + + if (!visitLHSUnlessError7_2(lab)) + return false; + for (auto i = 0u; i < visitedLHSUnlessError7Accepting.size(); i++) { + if (visitedLHSUnlessError7Accepting[i] && !visitedRHSUnlessError7Accepting[i]) { + cexLab = &*std::find_if(g.label_begin(), g.label_end(), [&](auto &lab){ return lab.getStamp() == i; }); + return false; + } + } + return true; +} + +bool TSODriver::checkError7(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError7(lab)) + return true; + + return visitError7(lab); +} +bool TSODriver::visitError8(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool TSODriver::visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && lab->isNotAtomic() && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && pLab->isNotAtomic() && llvm::isa(pLab)) { + if (!visitLHSUnlessError8_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessError8Accepting.clear(); + visitedLHSUnlessError8Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(0); + + return true + && visitLHSUnlessError8_1(lab, v); +} + +bool TSODriver::checkError8(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessError8(lab)) + return true; + + return visitError8(lab); +} +bool TSODriver::visitWarning9(const EventLabel *lab) const +{ + return false; +} + +bool TSODriver::visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (!v.contains(lab->getPos())) { +cexLab = lab; + return false; + } + + + return true; +} + +bool TSODriver::visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const +{ + auto &g = getGraph(); + + + if (true && llvm::isa(lab))for (auto &tmp : samelocs(g, lab)) if (auto *pLab = &tmp; true)if (true && llvm::isa(pLab)) { + if (!visitLHSUnlessWarning9_0(pLab, v)){ + return false; + } + + } + + return true; +} + +bool TSODriver::visitUnlessWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + visitedLHSUnlessWarning9Accepting.clear(); + visitedLHSUnlessWarning9Accepting.resize(g.getMaxStamp().get() + 1, false); + auto &v = lab->view(1); + + return true + && visitLHSUnlessWarning9_1(lab, v); +} + +bool TSODriver::checkWarning9(const EventLabel *lab) const +{ + auto &g = getGraph(); + + + if (visitUnlessWarning9(lab)) + return true; + + return visitWarning9(lab); +} +VerificationError TSODriver::checkErrors(const EventLabel *lab, const EventLabel *&race) const +{ + if (!checkError2(lab)) { + race = cexLab; + return VerificationError::VE_AccessNonMalloc; + } + + if (!checkError3(lab)) { + race = cexLab; + return VerificationError::VE_DoubleFree; + } + + if (!checkError4(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError5(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError6(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError7(lab)) { + race = cexLab; + return VerificationError::VE_AccessFreed; + } + + if (!checkError8(lab)) { + race = cexLab; + return VerificationError::VE_RaceNotAtomic; + } + + return VerificationError::VE_OK; +} + +std::vector TSODriver::checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const +{ + std::vector result; + + if (seenWarnings.count(VerificationError::VE_WWRace) == 0 && !checkWarning9(lab)) { + racyLabs.push_back(cexLab); + result.push_back(VerificationError::VE_WWRace); + } + + return result; +} + +bool TSODriver::isConsistent(const EventLabel *lab) const +{ + + return true + && checkConsAcyclic1(lab); +} + +View TSODriver::calcPPoRfBefore(const EventLabel *lab) const +{ + auto &g = getGraph(); + View pporf; + pporf.updateIdx(lab->getPos()); + + auto *pLab = g.getPreviousLabel(lab); + if (!pLab) + return pporf; + pporf.update(pLab->getPrefixView()); + if (auto *rLab = llvm::dyn_cast(pLab)) + pporf.update(rLab->getRf()->getPrefixView()); + if (auto *tsLab = llvm::dyn_cast(pLab)) + pporf.update(g.getEventLabel(tsLab->getParentCreate())->getPrefixView()); + if (auto *tjLab = llvm::dyn_cast(pLab)) + pporf.update(g.getLastThreadLabel(tjLab->getChildId())->getPrefixView()); + return pporf; +} +std::unique_ptr TSODriver::calculatePrefixView(const EventLabel *lab) const +{ + return std::make_unique(calcPPoRfBefore(lab)); +} diff --git a/src/Verification/Consistency/TSODriver.hpp b/src/Verification/Consistency/TSODriver.hpp new file mode 100644 index 0000000..6f80409 --- /dev/null +++ b/src/Verification/Consistency/TSODriver.hpp @@ -0,0 +1,243 @@ +/* + * GenMC -- Generic Model Checking. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-3.0.html. + * + * Author: Michalis Kokologiannakis + */ + +/******************************************************************************* + * CAUTION: This file is generated automatically by Kater -- DO NOT EDIT. + *******************************************************************************/ + +#ifndef GENMC_TSO_DRIVER_HPP +#define GENMC_TSO_DRIVER_HPP + +#include "config.h" +#include "ADT/VSet.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Verification/GenMCDriver.hpp" +#include "Verification/VerificationError.hpp" +#include +#include + +class TSODriver : public GenMCDriver { + +private: + enum class NodeStatus : unsigned char { unseen, entered, left }; + + struct NodeVisitStatus { + NodeVisitStatus() = default; + NodeVisitStatus(uint32_t c, NodeStatus s) : count(c), status(s) {} + uint32_t count{}; + NodeStatus status{}; + }; + +public: + TSODriver(std::shared_ptr conf, std::unique_ptr mod, + std::unique_ptr MI, GenMCDriver::Mode mode = GenMCDriver::VerificationMode{}); + + void calculateSaved(EventLabel *lab); + void calculateViews(EventLabel *lab); + void updateMMViews(EventLabel *lab) override; + bool isDepTracking() const override; + bool isConsistent(const EventLabel *lab) const override; + VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const override; + std::vector checkWarnings(const EventLabel *lab, const VSet &seenWarnings, std::vector &racyLabs) const; + std::unique_ptr calculatePrefixView(const EventLabel *lab) const override; + const View &getHbView(const EventLabel *lab) const override; + std::vector getCoherentStores(SAddr addr, Event read) override; + std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) override; + std::vector getCoherentPlacings(SAddr addr, Event store, bool isRMW) override; + +private: + bool isWriteRfBefore(Event a, Event b); + std::vector getInitRfsAtLoc(SAddr addr); + bool isHbOptRfBefore(const Event e, const Event write); + ExecutionGraph::co_iterator splitLocMOBefore(SAddr addr, Event e); + ExecutionGraph::co_iterator splitLocMOAfterHb(SAddr addr, const Event read); + ExecutionGraph::co_iterator splitLocMOAfter(SAddr addr, const Event e); + std::vector getMOOptRfAfter(const WriteLabel *sLab); + std::vector getMOInvOptRfAfter(const WriteLabel *sLab); + mutable const EventLabel *cexLab{}; + + mutable std::vector visitedCalc57_0; + mutable std::vector visitedCalc57_1; + mutable std::vector visitedCalc57_2; + mutable std::vector visitedCalc57_3; + + bool visitCalc57_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc57_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc57(const EventLabel *lab) const; + const View&getHbStableView(const EventLabel *lab) const { return lab->view(0); } + + auto checkCalc57(const EventLabel *lab) const; + mutable std::vector visitedCalc62_0; + mutable std::vector visitedCalc62_1; + mutable std::vector visitedCalc62_2; + mutable std::vector visitedCalc62_3; + + bool visitCalc62_0(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_1(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_2(const EventLabel *lab, View &calcRes) const; + bool visitCalc62_3(const EventLabel *lab, View &calcRes) const; + + View visitCalc62(const EventLabel *lab) const; + const View&getPorfStableView(const EventLabel *lab) const { return lab->view(1); } + + auto checkCalc62(const EventLabel *lab) const; + mutable std::vector visitedCoherence_0; + mutable std::vector visitedCoherence_1; + mutable std::vector visitedCoherence_2; + mutable uint32_t visitedCoherenceAccepting; + + bool visitCoherence_0(const EventLabel *lab) const; + bool visitCoherence_1(const EventLabel *lab) const; + bool visitCoherence_2(const EventLabel *lab) const; + + bool visitCoherenceFull() const; + + mutable std::vector visitedConsAcyclic1_0; + mutable std::vector visitedConsAcyclic1_1; + mutable std::vector visitedConsAcyclic1_2; + mutable std::vector visitedConsAcyclic1_3; + mutable uint32_t visitedConsAcyclic1Accepting; + + bool visitConsAcyclic1_0(const EventLabel *lab) const; + bool visitConsAcyclic1_1(const EventLabel *lab) const; + bool visitConsAcyclic1_2(const EventLabel *lab) const; + bool visitConsAcyclic1_3(const EventLabel *lab) const; + + bool visitConsAcyclic1(const EventLabel *lab) const; + + bool visitConsAcyclic1Full() const; + + bool checkUnlessConsAcyclic1(const EventLabel *lab) { return false; } + bool checkConsAcyclic1(const EventLabel *lab) const; + bool visitError2(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError2_0; + mutable std::vector visitedLHSUnlessError2_1; + + bool visitLHSUnlessError2_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError2_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError2Accepting; + bool visitUnlessError2(const EventLabel *lab) const; + bool checkError2(const EventLabel *lab) const; + bool visitError3(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError3_0; + mutable std::vector visitedLHSUnlessError3_1; + + bool visitLHSUnlessError3_0(const EventLabel *lab) const; + bool visitLHSUnlessError3_1(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError3Accepting; + mutable std::vector visitedRHSUnlessError3Accepting; + bool visitUnlessError3(const EventLabel *lab) const; + bool checkError3(const EventLabel *lab) const; + bool visitError4(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError4_0; + mutable std::vector visitedLHSUnlessError4_1; + mutable std::vector visitedLHSUnlessError4_2; + + bool visitLHSUnlessError4_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError4_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError4Accepting; + bool visitUnlessError4(const EventLabel *lab) const; + bool checkError4(const EventLabel *lab) const; + bool visitError5(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError5_0; + mutable std::vector visitedLHSUnlessError5_1; + mutable std::vector visitedLHSUnlessError5_2; + + bool visitLHSUnlessError5_0(const EventLabel *lab) const; + bool visitLHSUnlessError5_1(const EventLabel *lab) const; + bool visitLHSUnlessError5_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError5Accepting; + mutable std::vector visitedRHSUnlessError5Accepting; + bool visitUnlessError5(const EventLabel *lab) const; + bool checkError5(const EventLabel *lab) const; + bool visitError6(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError6_0; + mutable std::vector visitedLHSUnlessError6_1; + mutable std::vector visitedLHSUnlessError6_2; + + bool visitLHSUnlessError6_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_1(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError6_2(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError6Accepting; + bool visitUnlessError6(const EventLabel *lab) const; + bool checkError6(const EventLabel *lab) const; + bool visitError7(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError7_0; + mutable std::vector visitedLHSUnlessError7_1; + mutable std::vector visitedLHSUnlessError7_2; + + bool visitLHSUnlessError7_0(const EventLabel *lab) const; + bool visitLHSUnlessError7_1(const EventLabel *lab) const; + bool visitLHSUnlessError7_2(const EventLabel *lab) const; + + + + mutable std::vector visitedLHSUnlessError7Accepting; + mutable std::vector visitedRHSUnlessError7Accepting; + bool visitUnlessError7(const EventLabel *lab) const; + bool checkError7(const EventLabel *lab) const; + bool visitError8(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessError8_0; + mutable std::vector visitedLHSUnlessError8_1; + + bool visitLHSUnlessError8_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessError8_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessError8Accepting; + bool visitUnlessError8(const EventLabel *lab) const; + bool checkError8(const EventLabel *lab) const; + bool visitWarning9(const EventLabel *lab) const; + mutable std::vector visitedLHSUnlessWarning9_0; + mutable std::vector visitedLHSUnlessWarning9_1; + + bool visitLHSUnlessWarning9_0(const EventLabel *lab, const View &v) const; + bool visitLHSUnlessWarning9_1(const EventLabel *lab, const View &v) const; + + mutable std::vector visitedLHSUnlessWarning9Accepting; + bool visitUnlessWarning9(const EventLabel *lab) const; + bool checkWarning9(const EventLabel *lab) const; + + void visitPPoRf0(const EventLabel *lab, View &pporf) const; + void visitPPoRf1(const EventLabel *lab, View &pporf) const; + + View calcPPoRfBefore(const EventLabel *lab) const; + + mutable std::vector visitedPPoRf0; + mutable std::vector visitedPPoRf1; + + +}; + +#endif /* GENMC_TSO_DRIVER_HPP */ diff --git a/src/DriverFactory.hpp b/src/Verification/DriverFactory.hpp similarity index 82% rename from src/DriverFactory.hpp rename to src/Verification/DriverFactory.hpp index 2f1adcb..08d2311 100644 --- a/src/DriverFactory.hpp +++ b/src/Verification/DriverFactory.hpp @@ -18,15 +18,15 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DRIVER_FACTORY_HPP__ -#define __DRIVER_FACTORY_HPP__ +#ifndef GENMC_DRIVER_FACTORY_HPP +#define GENMC_DRIVER_FACTORY_HPP -#include "Config.hpp" -#include "IMMDriver.hpp" -#include "RADriver.hpp" -#include "RC11Driver.hpp" -#include "SCDriver.hpp" -#include "TSODriver.hpp" +#include "Config/Config.hpp" +#include "Verification/Consistency/IMMDriver.hpp" +#include "Verification/Consistency/RADriver.hpp" +#include "Verification/Consistency/RC11Driver.hpp" +#include "Verification/Consistency/SCDriver.hpp" +#include "Verification/Consistency/TSODriver.hpp" #include class DriverFactory { @@ -64,4 +64,4 @@ class DriverFactory { } }; -#endif /* __DRIVER_FACTORY_HPP__ */ +#endif /* GENMC_DRIVER_FACTORY_HPP */ diff --git a/src/DriverHandlerDispatcher.hpp b/src/Verification/DriverHandlerDispatcher.hpp similarity index 72% rename from src/DriverHandlerDispatcher.hpp rename to src/Verification/DriverHandlerDispatcher.hpp index 00ae60f..cf16cfa 100644 --- a/src/DriverHandlerDispatcher.hpp +++ b/src/Verification/DriverHandlerDispatcher.hpp @@ -18,13 +18,13 @@ * Author: Michalis Kokologiannakis */ -#ifndef __DRIVER_HANDLER_DISPATCHER_HPP__ -#define __DRIVER_HANDLER_DISPATCHER_HPP__ +#ifndef GENMC_DRIVER_HANDLER_DISPATCHER_HPP +#define GENMC_DRIVER_HANDLER_DISPATCHER_HPP -#include "Error.hpp" -#include "EventLabel.hpp" -#include "GenMCDriver.hpp" -#include "LabelVisitor.hpp" +#include "ExecutionGraph/EventLabel.hpp" +#include "ExecutionGraph/LabelVisitor.hpp" +#include "Support/Error.hpp" +#include "Verification/GenMCDriver.hpp" /******************************************************************************* ** DriverHandlerDispatcher Class @@ -43,11 +43,15 @@ class DriverHandlerDispatcher : public LabelVisitor { driver->handleBlock(std::unique_ptr( static_cast(lab.clone().release()))); } - - void visitOptionalLabel(const OptionalLabel &lab) + void visitThreadKillLabel(const ThreadKillLabel &lab) { - driver->handleOptional(std::unique_ptr( - static_cast(lab.clone().release()))); + driver->handleThreadKill(std::unique_ptr( + static_cast(lab.clone().release()))); + } + void visitThreadFinishLabel(const ThreadFinishLabel &lab) + { + driver->handleThreadFinish(std::unique_ptr( + static_cast(lab.clone().release()))); } void visitReadLabel(const ReadLabel &lab) @@ -56,52 +60,34 @@ class DriverHandlerDispatcher : public LabelVisitor { static_cast(lab.clone().release()))); } - void visitDskReadLabel(const DskReadLabel &lab) - { - driver->handleDskRead(std::unique_ptr( - static_cast(lab.clone().release()))); - } - void visitWriteLabel(const WriteLabel &lab) { driver->handleStore(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitDskWriteLabel(const DskWriteLabel &lab) - { - driver->handleDskWrite(std::unique_ptr( - static_cast(lab.clone().release()))); - } - void visitFenceLabel(const FenceLabel &lab) { driver->handleFence(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitCLFlushLabel(const CLFlushLabel &lab) - { - driver->handleCLFlush(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - void visitDskFsyncLabel(const DskFsyncLabel &lab) + void visitOptionalLabel(const OptionalLabel &lab) { - driver->handleDskFsync(std::unique_ptr( - static_cast(lab.clone().release()))); + driver->handleOptional(std::unique_ptr( + static_cast(lab.clone().release()))); } - void visitDskSyncLabel(const DskSyncLabel &lab) + void visitMallocLabel(const MallocLabel &lab) { - driver->handleDskSync(std::unique_ptr( - static_cast(lab.clone().release()))); + driver->handleMalloc(std::unique_ptr( + static_cast(lab.clone().release()))); } - void visitDskPbarrierLabel(const DskPbarrierLabel &lab) + void visitFreeLabel(const FreeLabel &lab) { - driver->handleDskPbarrier(std::unique_ptr( - static_cast(lab.clone().release()))); + driver->handleFree(std::unique_ptr( + static_cast(lab.clone().release()))); } void visitThreadCreateLabel(const ThreadCreateLabel &lab) @@ -109,80 +95,43 @@ class DriverHandlerDispatcher : public LabelVisitor { driver->handleThreadCreate(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitThreadJoinLabel(const ThreadJoinLabel &lab) { driver->handleThreadJoin(std::unique_ptr( static_cast(lab.clone().release()))); } - - void visitThreadFinishLabel(const ThreadFinishLabel &lab) - { - driver->handleThreadFinish(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - void visitMallocLabel(const MallocLabel &lab) - { - driver->handleMalloc(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - void visitFreeLabel(const FreeLabel &lab) - { - driver->handleFree(std::unique_ptr( - static_cast(lab.clone().release()))); - } - void visitHpProtectLabel(const HpProtectLabel &lab) { - driver->handleHpProtect(std::unique_ptr( + driver->handleDummy(std::unique_ptr( static_cast(lab.clone().release()))); } - + void visitHelpingCasLabel(const HelpingCasLabel &lab) + { + driver->handleHelpingCas(std::unique_ptr( + static_cast(lab.clone().release()))); + } void visitLoopBeginLabel(const LoopBeginLabel &lab) { - driver->handleLoopBegin(std::unique_ptr( + driver->handleDummy(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitSpinStartLabel(const SpinStartLabel &lab) { driver->handleSpinStart(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitFaiZNESpinEndLabel(const FaiZNESpinEndLabel &lab) { driver->handleFaiZNESpinEnd(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitLockZNESpinEndLabel(const LockZNESpinEndLabel &lab) { driver->handleLockZNESpinEnd(std::unique_ptr( static_cast(lab.clone().release()))); } - void visitThreadKillLabel(const ThreadKillLabel &lab) - { - driver->handleThreadKill(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - void visitHelpingCasLabel(const HelpingCasLabel &lab) - { - driver->handleHelpingCas(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - void visitDskOpenLabel(const DskOpenLabel &lab) - { - driver->handleDskOpen(std::unique_ptr( - static_cast(lab.clone().release()))); - } - - /* Generic handlers */ + /* Start,Init etc should never be handled here */ void visitEventLabel(const EventLabel &lab) { BUG(); } @@ -190,4 +139,4 @@ class DriverHandlerDispatcher : public LabelVisitor { GenMCDriver *driver; }; -#endif /* __DRIVER_HANDLER_DISPATCHER_HPP__ */ +#endif /* GENMC_DRIVER_HANDLER_DISPATCHER_HPP */ diff --git a/src/GenMCDriver.cpp b/src/Verification/GenMCDriver.cpp similarity index 82% rename from src/GenMCDriver.cpp rename to src/Verification/GenMCDriver.cpp index b511c55..266cac4 100644 --- a/src/GenMCDriver.cpp +++ b/src/Verification/GenMCDriver.cpp @@ -19,20 +19,20 @@ */ #include "GenMCDriver.hpp" -#include "BoundDecider.hpp" -#include "Config.hpp" -#include "DepExecutionGraph.hpp" -#include "DriverHandlerDispatcher.hpp" -#include "Error.hpp" -#include "GraphIterators.hpp" -#include "Interpreter.h" -#include "LLVMModule.hpp" -#include "LabelVisitor.hpp" -#include "Logger.hpp" -#include "MaximalIterator.hpp" -#include "Parser.hpp" -#include "SExprVisitor.hpp" -#include "ThreadPool.hpp" +#include "Config/Config.hpp" +#include "ExecutionGraph/DepExecutionGraph.hpp" +#include "ExecutionGraph/GraphIterators.hpp" +#include "ExecutionGraph/LabelVisitor.hpp" +#include "ExecutionGraph/MaximalIterator.hpp" +#include "Runtime/Interpreter.h" +#include "Static/LLVMModule.hpp" +#include "Support/Error.hpp" +#include "Support/Logger.hpp" +#include "Support/Parser.hpp" +#include "Support/SExprVisitor.hpp" +#include "Support/ThreadPool.hpp" +#include "Verification/Consistency/BoundDecider.hpp" +#include "Verification/DriverHandlerDispatcher.hpp" #include "config.h" #include #include @@ -98,9 +98,9 @@ GenMCDriver::Execution::~Execution() = default; void repairRead(ExecutionGraph &g, ReadLabel *lab) { - auto last = (store_rbegin(g, lab->getAddr()) == store_rend(g, lab->getAddr())) + auto last = (g.co_rbegin(lab->getAddr()) == g.co_rend(lab->getAddr())) ? Event::getInit() - : store_rbegin(g, lab->getAddr())->getPos(); + : g.co_rbegin(lab->getAddr())->getPos(); g.changeRf(lab->getPos(), last); lab->setAddedMax(true); lab->setIPRStatus(g.getEventLabel(last)->getStamp() > lab->getStamp()); @@ -251,7 +251,7 @@ bool GenMCDriver::isSchedulable(int thread) const { auto &thr = getEE()->getThrById(thread); auto *lab = getGraph().getLastThreadLabel(thread); - return !thr.ECStack.empty() && !lab->isTerminator(); + return !thr.ECStack.empty() && !llvm::isa(lab); } bool GenMCDriver::schedulePrioritized() @@ -299,7 +299,7 @@ bool GenMCDriver::isNextThreadInstLoad(int tid) auto &I = getEE()->getThrById(tid).ECStack.back().CurInst; /* Overapproximate with function calls some of which might be modeled as loads */ - auto *ci = llvm::dyn_cast(I); + auto *ci = llvm::dyn_cast(I); return llvm::isa(I) || llvm::isa(I) || llvm::isa(I) || (ci && ci->getCalledFunction() && @@ -473,8 +473,7 @@ std::pair, Event> GenMCDriver::extractValPrefix(Event pos) for (auto i = 0u; i < pos.index; i++) { auto *lab = g.getEventLabel(Event(pos.thread, i)); if (auto *rLab = llvm::dyn_cast(lab)) { - auto *drLab = llvm::dyn_cast(rLab); - vals.push_back(drLab ? getDskReadValue(drLab) : getReadValue(rLab)); + vals.push_back(getReadValue(rLab)); last = lab->getPos(); } else if (auto *jLab = llvm::dyn_cast(lab)) { vals.push_back(getJoinValue(jLab)); @@ -494,10 +493,11 @@ std::pair, Event> GenMCDriver::extractValPrefix(Event pos) Event findNextLabelToAdd(const ExecutionGraph &g, Event pos) { - auto first = Event(pos.thread, 0); - auto it = std::find_if(po_succ_begin(g, first), po_succ_end(g, first), - [&](auto &lab) { return llvm::isa(&lab); }); - return it == po_succ_end(g, first) ? g.getLastThreadEvent(pos.thread).next() : it->getPos(); + const auto *firstLab = g.getFirstThreadLabel(pos.thread); + auto succs = po_succs(g, firstLab); + auto it = + std::ranges::find_if(succs, [&](auto &lab) { return llvm::isa(&lab); }); + return it == succs.end() ? g.getLastThreadEvent(pos.thread).next() : (*it).getPos(); } bool GenMCDriver::tryOptimizeScheduling(Event pos) @@ -547,7 +547,7 @@ void GenMCDriver::checkHelpingCasAnnotation() /* Check that all stores that would make this helping * CAS succeed are read by a helped CAS. * We don't need to check the swap value of the helped CAS */ - if (std::any_of(store_begin(g, hLab->getAddr()), store_end(g, hLab->getAddr()), + if (std::any_of(g.co_begin(hLab->getAddr()), g.co_end(hLab->getAddr()), [&](auto &sLab) { return hLab->getExpected() == sLab.getVal() && std::none_of( @@ -649,50 +649,52 @@ void GenMCDriver::handleExecutionEnd() return; } - if (fullExecutionExceedsBound()) - ++result.boundExceeding; - + if (getConf()->warnUnfreedMemory) + checkUnfreedMemory(); if (getConf()->printExecGraphs && !getConf()->persevere) printGraph(); /* Delay printing if persevere is enabled */ GENMC_DEBUG(if (getConf()->boundsHistogram && !inEstimationMode()) trackExecutionBound();); ++result.explored; + if (fullExecutionExceedsBound()) + ++result.boundExceeding; } void GenMCDriver::handleRecoveryStart() { - if (isExecutionBlocked()) - return; - - auto &g = getGraph(); - auto *EE = getEE(); - - /* Make sure that a thread for the recovery routine is - * added only once in the execution graph*/ - if (g.getRecoveryRoutineId() == -1) - g.addRecoveryThread(); - - /* We will create a start label for the recovery thread. - * We synchronize with a persistency barrier, if one exists, - * otherwise, we synchronize with nothing */ - auto tid = g.getRecoveryRoutineId(); - auto psb = g.collectAllEvents( - [&](const EventLabel *lab) { return llvm::isa(lab); }); - if (psb.empty()) - psb.push_back(Event::getInit()); - ERROR_ON(psb.size() > 1, "Usage of only one persistency barrier is allowed!\n"); - - auto tsLab = ThreadStartLabel::create(Event(tid, 0), psb.back(), - ThreadInfo(tid, psb.back().thread, 0, 0)); - auto *lab = addLabelToGraph(std::move(tsLab)); - - /* Create a thread for the interpreter, and appropriately - * add it to the thread list (pthread_create() style) */ - EE->createAddRecoveryThread(tid); - - /* Finally, do all necessary preparations in the interpreter */ - getEE()->setupRecoveryRoutine(tid); + BUG(); + // if (isExecutionBlocked()) + // return; + + // auto &g = getGraph(); + // auto *EE = getEE(); + + // /* Make sure that a thread for the recovery routine is + // * added only once in the execution graph*/ + // if (g.getRecoveryRoutineId() == -1) + // g.addRecoveryThread(); + + // /* We will create a start label for the recovery thread. + // * We synchronize with a persistency barrier, if one exists, + // * otherwise, we synchronize with nothing */ + // auto tid = g.getRecoveryRoutineId(); + // auto psb = g.collectAllEvents( + // [&](const EventLabel *lab) { return llvm::isa(lab); }); + // if (psb.empty()) + // psb.push_back(Event::getInit()); + // ERROR_ON(psb.size() > 1, "Usage of only one persistency barrier is allowed!\n"); + + // auto tsLab = ThreadStartLabel::create(Event(tid, 0), psb.back(), + // ThreadInfo(tid, psb.back().thread, 0, 0)); + // auto *lab = addLabelToGraph(std::move(tsLab)); + + // /* Create a thread for the interpreter, and appropriately + // * add it to the thread list (pthread_create() style) */ + // EE->createAddRecoveryThread(tid); + + // /* Finally, do all necessary preparations in the interpreter */ + // getEE()->setupRecoveryRoutine(tid); return; } @@ -792,7 +794,10 @@ void GenMCDriver::blockThread(std::unique_ptr bLab) * 2) If addLabelToGraph() does extra stuff (e.g., event caching) we absolutely * don't want to do that here. blockThread() should be safe to call from * anywhere in the code, with no unexpected side-effects */ - getGraph().addLabelToGraph(std::move(bLab)); + auto &g = getGraph(); + if (bLab->getPos() == g.getLastThreadEvent(bLab->getThread())) + g.removeLast(bLab->getThread()); + g.addLabelToGraph(std::move(bLab)); } void GenMCDriver::blockThreadTryMoot(std::unique_ptr bLab) @@ -942,11 +947,6 @@ bool isUninitializedAccess(const SAddr &addr, const Event &pos) return addr.isDynamic() && pos.isInitializer(); } -bool readsUninitializedMem(const ReadLabel *lab) -{ - return isUninitializedAccess(lab->getAddr(), lab->getRf()->getPos()); -} - bool GenMCDriver::isRevisitValid(const Revisit &revisit) { auto &g = getGraph(); @@ -961,13 +961,11 @@ bool GenMCDriver::isRevisitValid(const Revisit &revisit) return false; auto *rLab = llvm::dyn_cast(mLab); - if (rLab && readsUninitializedMem(rLab)) { - reportError(pos, VerificationError::VE_UninitializedMem); + if (rLab && checkInitializedMem(rLab) != VerificationError::VE_OK) return false; - } /* If an extra event is added, re-check consistency */ - auto *nLab = g.getNextLabel(pos); + auto *nLab = g.getNextLabel(mLab); return !g.isRMWLoad(pos) || (isExecutionValid(nLab) && checkForRaces(nLab) == VerificationError::VE_OK); } @@ -976,11 +974,8 @@ bool GenMCDriver::isExecutionDrivenByGraph(const EventLabel *lab) { const auto &g = getGraph(); auto curr = lab->getPos(); - auto replay = (curr.index < g.getThreadSize(curr.thread)) && - !llvm::isa(g.getEventLabel(curr)); - if (!replay && !llvm::isa(lab) && !llvm::isa(lab)) - cacheEventLabel(lab); - return replay; + return (curr.index < g.getThreadSize(curr.thread)) && + !llvm::isa(g.getEventLabel(curr)); } bool GenMCDriver::executionExceedsBound(BoundCalculationStrategy strategy) const @@ -1011,11 +1006,35 @@ bool GenMCDriver::inReplay() const return getEE()->getExecState() == llvm::ExecutionState::Replay; } +MallocLabel *findAllocatingLabel(ExecutionGraph &g, const SAddr &addr) +{ + /* Don't iterate over the graph if you don't have to */ + if (!addr.isDynamic()) + return nullptr; + + auto labIt = std::find_if(g.label_begin(), g.label_end(), [&](auto &lab) { + auto *mLab = llvm::dyn_cast(&lab); + return mLab && mLab->contains(addr); + }); + if (labIt != g.label_end()) + return llvm::dyn_cast(&*labIt); + return nullptr; +} + EventLabel *GenMCDriver::addLabelToGraph(std::unique_ptr lab) { auto &g = getGraph(); + + /* Cache the event before updating views (inits are added w/ tcreate) */ + if (lab->getIndex() > 0) + cacheEventLabel(&*lab); + + /* Add and update views */ auto *addedLab = g.addLabelToGraph(std::move(lab)); updateLabelViews(addedLab); + if (auto *mLab = llvm::dyn_cast(addedLab)) + g.addAlloc(findAllocatingLabel(g, mLab->getAddr()), mLab); + lastAdded = addedLab->getPos(); if (addedLab->getIndex() >= getConf()->warnOnGraphSize) { LOG_ONCE("large-graph", VerbosityLevel::Tip) @@ -1040,11 +1059,17 @@ VerificationError GenMCDriver::checkForRaces(const EventLabel *lab) if (getConf()->disableRaceDetection || inEstimationMode()) return VerificationError::VE_OK; + /* Bounding: extensibility not guaranteed; RD should be disabled */ + if (llvm::isa(lab) && !checkAtomicity(llvm::dyn_cast(lab))) { + BUG_ON(!getConf()->bound.has_value()); + return VerificationError::VE_OK; + } + /* Check for hard errors */ const EventLabel *racyLab = nullptr; auto err = checkErrors(lab, racyLab); if (err != VerificationError::VE_OK) { - reportError(lab->getPos(), err, "", racyLab); + reportError({lab->getPos(), err, "", racyLab}); return err; } @@ -1130,10 +1155,10 @@ SVal GenMCDriver::getWriteValue(const EventLabel *lab, const AAccess &access) * the one the write's (see troep.c). In any case though, the * sizes should match */ if (wLab->getSize() != access.getSize()) - reportError(wLab->getPos(), VerificationError::VE_MixedSize, - "Mixed-size accesses detected: tried to read event with a " + - std::to_string(access.getSize().get() * 8) + "-bit access!\n" + - "Please check the LLVM-IR.\n"); + reportError({wLab->getPos(), VerificationError::VE_MixedSize, + "Mixed-size accesses detected: tried to read event with a " + + std::to_string(access.getSize().get() * 8) + "-bit access!\n" + + "Please check the LLVM-IR.\n"}); /* If the size of the R and the W are the same, we are done */ return wLab->getVal(); @@ -1169,7 +1194,7 @@ SVal GenMCDriver::getStartValue(const ThreadStartLabel *bLab) const SVal GenMCDriver::getBarrierInitValue(const AAccess &access) { const auto &g = getGraph(); - auto sIt = std::find_if(store_begin(g, access.getAddr()), store_end(g, access.getAddr()), + auto sIt = std::find_if(g.co_begin(access.getAddr()), g.co_end(access.getAddr()), [&access, &g](auto &bLab) { BUG_ON(!llvm::isa(bLab)); return bLab.getAddr() == access.getAddr() && @@ -1177,7 +1202,7 @@ SVal GenMCDriver::getBarrierInitValue(const AAccess &access) }); /* All errors pertinent to initialization should be captured elsewhere */ - BUG_ON(sIt == store_end(g, access.getAddr())); + BUG_ON(sIt == g.co_end(access.getAddr())); return getWriteValue(&*sIt, access); } @@ -1192,7 +1217,7 @@ std::optional GenMCDriver::getReadRetValue(const ReadLabel *rLab) /* Reading a non-init barrier value means that the thread should block */ auto res = getReadValue(rLab); BUG_ON(llvm::isa(rLab) && res != getBarrierInitValue(rLab->getAccess()) && - !getGraph().getLastThreadLabel(rLab->getThread())->isTerminator()); + !llvm::isa(getGraph().getLastThreadLabel(rLab->getThread()))); return {res}; } @@ -1226,142 +1251,128 @@ bool GenMCDriver::isHazptrProtected(const MemAccessLabel *mLab) const for (auto j = pLab->getIndex() + 1; j < mLab->getIndex(); j++) { auto *lab = g.getEventLabel(Event(mLab->getThread(), j)); - if (auto *oLab = dyn_cast(lab)) + if (auto *oLab = llvm::dyn_cast(lab)) if (oLab->getHpAddr() == pLab->getHpAddr()) return false; } return true; } -MallocLabel *findAllocatingLabel(const ExecutionGraph &g, const SAddr &addr) -{ - auto labIt = std::find_if(label_begin(g), label_end(g), [&](auto &lab) { - auto *mLab = llvm::dyn_cast(&lab); - return mLab && mLab->contains(addr); - }); - if (labIt != label_end(g)) - return llvm::dyn_cast(&*labIt); - return nullptr; -} - -bool GenMCDriver::isAccessValid(const MemAccessLabel *lab) const +VerificationError GenMCDriver::checkAccessValidity(const MemAccessLabel *lab) { - /* Make sure that the interperter is aware of this static variable */ - if (!lab->getAddr().isDynamic()) - return getEE()->isStaticallyAllocated(lab->getAddr()); - - /* Dynamic accesses are valid if they access allocated memory */ - auto &g = getGraph(); - return !lab->getAddr().isNull() && findAllocatingLabel(g, lab->getAddr()); + /* Static variable validity is handled by the interpreter. * + * Dynamic accesses are valid if they access allocated memory */ + if ((!lab->getAddr().isDynamic() && !getEE()->isStaticallyAllocated(lab->getAddr())) || + (lab->getAddr().isDynamic() && !lab->getAlloc())) { + reportError({lab->getPos(), VerificationError::VE_AccessNonMalloc}); + return VerificationError::VE_AccessNonMalloc; + } + return VerificationError::VE_OK; } -void GenMCDriver::checkLockValidity(const ReadLabel *rLab, const std::vector &rfs) +VerificationError GenMCDriver::checkInitializedMem(const ReadLabel *rLab) { - auto *lLab = llvm::dyn_cast(rLab); - if (!lLab) - return; + // FIXME: Have label for mutex-destroy and check type instead of val. + // Also for barriers. - /* Should not read from destroyed mutex */ - auto rfIt = std::find_if(rfs.cbegin(), rfs.cend(), [this, lLab](const Event &rf) { - auto rfVal = getWriteValue(getGraph().getEventLabel(rf), lLab->getAccess()); - return rfVal == SVal(-1); - }); - if (rfIt != rfs.cend()) - reportError(rLab->getPos(), VerificationError::VE_UninitializedMem, - "Called lock() on destroyed mutex!", getGraph().getEventLabel(*rfIt)); -} + /* Locks should not read from destroyed mutexes */ + const auto *lLab = llvm::dyn_cast(rLab); + if (lLab && getWriteValue(lLab->getRf(), lLab->getAccess()) == SVal(-1)) { + reportError({lLab->getPos(), VerificationError::VE_UninitializedMem, + "Called lock() on destroyed mutex!", lLab->getRf()}); + return VerificationError::VE_UninitializedMem; + } -void GenMCDriver::checkUnlockValidity(const WriteLabel *wLab) -{ - auto *uLab = llvm::dyn_cast(wLab); - if (!uLab) - return; + /* Barriers should read initialized, not-destroyed memory */ + const auto *bLab = llvm::dyn_cast(rLab); + if (bLab && bLab->getRf()->getPos().isInitializer()) { + reportError({rLab->getPos(), VerificationError::VE_UninitializedMem, + "Called barrier_wait() on uninitialized barrier!"}); + return VerificationError::VE_UninitializedMem; + } + if (bLab && getWriteValue(bLab->getRf(), bLab->getAccess()) == SVal(0)) { + reportError({rLab->getPos(), VerificationError::VE_AccessFreed, + "Called barrier_wait() on destroyed barrier!", bLab->getRf()}); + return VerificationError::VE_UninitializedMem; + } - /* Unlocks should unlock mutexes locked by the same thread */ - if (getGraph().getMatchingLock(uLab->getPos()).isInitializer()) { - reportError(uLab->getPos(), VerificationError::VE_InvalidUnlock, - "Called unlock() on mutex not locked by the same thread!"); + /* Plain events should read initialized memory if they are dynamic accesses */ + if (isUninitializedAccess(rLab->getAddr(), rLab->getRf()->getPos())) { + reportError({rLab->getPos(), VerificationError::VE_UninitializedMem}); + return VerificationError::VE_UninitializedMem; } + return VerificationError::VE_OK; } -void GenMCDriver::checkBInitValidity(const WriteLabel *lab) +VerificationError GenMCDriver::checkInitializedMem(const WriteLabel *wLab) { - auto *wLab = llvm::dyn_cast(lab); - if (!wLab) - return; - - /* Make sure the barrier hasn't already been initialized, and - * that the initializing value is greater than 0 */ auto &g = getGraph(); - auto sIt = std::find_if(store_begin(g, wLab->getAddr()), store_end(g, wLab->getAddr()), - [&g, wLab](auto &sLab) { - return &sLab != wLab && sLab.getAddr() == wLab->getAddr() && - llvm::isa(sLab); - }); - if (sIt != store_end(g, wLab->getAddr())) - reportError(wLab->getPos(), VerificationError::VE_InvalidBInit, - "Called barrier_init() multiple times!", &*sIt); - else if (wLab->getVal() == SVal(0)) - reportError(wLab->getPos(), VerificationError::VE_InvalidBInit, - "Called barrier_init() with 0!"); - return; -} - -void GenMCDriver::checkBIncValidity(const ReadLabel *rLab, const std::vector &rfs) -{ - auto *bLab = llvm::dyn_cast(rLab); - if (!bLab) - return; - - if (std::any_of(rfs.cbegin(), rfs.cend(), - [](const Event &rf) { return rf.isInitializer(); })) - reportError(rLab->getPos(), VerificationError::VE_UninitializedMem, - "Called barrier_wait() on uninitialized barrier!"); - else if (std::any_of(rfs.cbegin(), rfs.cend(), [this, bLab](const Event &rf) { - auto rfVal = - getWriteValue(getGraph().getEventLabel(rf), bLab->getAccess()); - return rfVal == SVal(0); - })) - reportError(rLab->getPos(), VerificationError::VE_AccessFreed, - "Called barrier_wait() on destroyed barrier!", bLab->getRf()); + /* Unlocks should unlock mutexes locked by the same thread */ + const auto *uLab = llvm::dyn_cast(wLab); + if (uLab && g.getMatchingLock(uLab->getPos()).isInitializer()) { + reportError({uLab->getPos(), VerificationError::VE_InvalidUnlock, + "Called unlock() on mutex not locked by the same thread!"}); + return VerificationError::VE_InvalidUnlock; + } + + /* Barriers should be initialized once, with a proper value */ + const auto *bLab = llvm::dyn_cast(wLab); + if (bLab && wLab->getVal() == SVal(0)) { + reportError({wLab->getPos(), VerificationError::VE_InvalidBInit, + "Called barrier_init() with 0!"}); + return VerificationError::VE_InvalidBInit; + } + if (bLab && + std::any_of(g.co_begin(bLab->getAddr()), g.co_end(bLab->getAddr()), [&](auto &sLab) { + return &sLab != wLab && sLab.getAddr() == wLab->getAddr() && + llvm::isa(sLab); + })) { + reportError({wLab->getPos(), VerificationError::VE_InvalidBInit, + "Called barrier_init() multiple times!"}); + return VerificationError::VE_InvalidBInit; + } + return VerificationError::VE_OK; } -void GenMCDriver::checkFinalAnnotations(const WriteLabel *wLab) +VerificationError GenMCDriver::checkFinalAnnotations(const WriteLabel *wLab) { if (!getConf()->helper) - return; + return VerificationError::VE_OK; auto &g = getGraph(); if (g.hasLocMoreThanOneStore(wLab->getAddr())) - return; + return VerificationError::VE_OK; if ((wLab->isFinal() && - std::any_of(store_begin(g, wLab->getAddr()), store_end(g, wLab->getAddr()), + std::any_of(g.co_begin(wLab->getAddr()), g.co_end(wLab->getAddr()), [&](auto &sLab) { return !getHbView(wLab).contains(sLab.getPos()); })) || - (!wLab->isFinal() && - std::any_of(store_begin(g, wLab->getAddr()), store_end(g, wLab->getAddr()), - [&](auto &sLab) { return sLab.isFinal(); }))) { - reportError(wLab->getPos(), VerificationError::VE_Annotation, - "Multiple stores at final location!"); - return; + (!wLab->isFinal() && std::any_of(g.co_begin(wLab->getAddr()), g.co_end(wLab->getAddr()), + [&](auto &sLab) { return sLab.isFinal(); }))) { + reportError({wLab->getPos(), VerificationError::VE_Annotation, + "Multiple stores at final location!"}); + return VerificationError::VE_Annotation; } - return; + return VerificationError::VE_OK; } -void GenMCDriver::checkIPRValidity(const ReadLabel *rLab) +VerificationError GenMCDriver::checkIPRValidity(const ReadLabel *rLab) { if (!rLab->getAnnot() || !getConf()->ipr) - return; + return VerificationError::VE_OK; auto &g = getGraph(); - auto racyIt = std::find_if(store_begin(g, rLab->getAddr()), store_end(g, rLab->getAddr()), + auto racyIt = std::find_if(g.co_begin(rLab->getAddr()), g.co_end(rLab->getAddr()), [&](auto &wLab) { return wLab.hasAttr(WriteAttr::WWRacy); }); - if (racyIt != store_end(g, rLab->getAddr())) { - auto msg = "Warning treated as an error due to in-place revisiting.\n" - "You can use -disable-ipr to disable this feature."s; - reportError(racyIt->getPos(), VerificationError::VE_WWRace, msg, nullptr, true); - } + if (racyIt == g.co_end(rLab->getAddr())) + return VerificationError::VE_OK; + + auto msg = "Unordered writes do not constitute a bug per se, though they often " + "indicate faulty design.\n" + "This warning is treated as an error due to in-place revisiting (IPR).\n" + "You can use -disable-ipr to disable this feature."s; + reportError({racyIt->getPos(), VerificationError::VE_WWRace, msg, nullptr, true}); + return VerificationError::VE_WWRace; } bool GenMCDriver::threadReadsMaximal(int tid) @@ -1414,21 +1425,44 @@ void GenMCDriver::checkLiveness() return threadReadsMaximal(tid); })) { /* Print some TID blocked by a spinloop */ - reportError(g.getLastThreadEvent(nonTermTID), VerificationError::VE_Liveness, - "Non-terminating spinloop: thread " + std::to_string(nonTermTID)); + reportError({g.getLastThreadEvent(nonTermTID), VerificationError::VE_Liveness, + "Non-terminating spinloop: thread " + std::to_string(nonTermTID)}); } return; } +void GenMCDriver::checkUnfreedMemory() +{ + if (isHalting()) + return; + + auto &g = getGraph(); + const MallocLabel *unfreedAlloc = nullptr; + if (std::ranges::any_of(g.labels(), [&](auto &lab) { + unfreedAlloc = llvm::dyn_cast(&lab); + return unfreedAlloc && unfreedAlloc->getFree() == nullptr; + })) { + reportWarningOnce(unfreedAlloc->getPos(), VerificationError::VE_UnfreedMemory); + } +} + void GenMCDriver::filterConflictingBarriers(const ReadLabel *lab, std::vector &stores) { - if (getConf()->disableBAM || !llvm::isa(lab)) + if (getConf()->disableBAM || + (!llvm::isa(lab) && !llvm::isa(lab))) return; + /* barrier_wait()'s plain load should read maximally */ + if (auto *rLab = llvm::dyn_cast(lab)) { + std::swap(stores[0], stores.back()); + stores.resize(1); + return; + } + /* barrier_wait()'s FAI loads should not read from conflicting stores */ auto &g = getGraph(); stores.erase(std::remove_if(stores.begin(), stores.end(), - [&](const Event &s) { + [&](auto &s) { return g.isStoreReadByExclusiveRead(s, lab->getAddr()); }), stores.end()); @@ -1662,8 +1696,11 @@ void GenMCDriver::filterValuesFromAnnotSAVER(const ReadLabel *rLab, std::vector< BUG_ON(validStores.empty()); } -void GenMCDriver::unblockWaitingHelping() +void GenMCDriver::unblockWaitingHelping(const WriteLabel *lab) { + if (!llvm::isa(lab)) + return; + /* FIXME: We have to wake up all threads waiting on helping CASes, * as we don't know which ones are from the same CAS */ for (auto i = 0u; i < getGraph().getNumThreads(); i++) { @@ -1723,32 +1760,49 @@ bool GenMCDriver::checkAtomicity(const WriteLabel *wLab) return true; } -bool GenMCDriver::ensureConsistentRf(const ReadLabel *rLab, std::vector &rfs) +std::optional GenMCDriver::findConsistentRf(const ReadLabel *rLab, std::vector &rfs) { auto &g = getGraph(); + /* For the non-bounding case, maximal extensibility guarantees consistency */ + if (!getConf()->bound.has_value()) { + g.changeRf(rLab->getPos(), rfs.back()); + return {rfs.back()}; + } + + /* Otherwise, search for a consistent rf */ while (!rfs.empty()) { g.changeRf(rLab->getPos(), rfs.back()); if (isExecutionValid(rLab)) - break; + return {rfs.back()}; rfs.erase(rfs.end() - 1); } - if (!rfs.empty()) - return true; - - BUG_ON(!getConf()->bound.has_value()); + /* If none is found, tough luck */ moot(); - return false; + return std::nullopt; } -bool GenMCDriver::ensureConsistentStore(const WriteLabel *wLab) +std::optional GenMCDriver::findConsistentCo(WriteLabel *wLab, std::vector &cos) { - if (!checkAtomicity(wLab) || !isExecutionValid(wLab)) { - moot(); - return false; + auto &g = getGraph(); + + /* Similarly to the read case: rely on extensibility */ + g.addStoreToCOAfter(wLab, g.getEventLabel(cos.back())); + if (!getConf()->bound.has_value()) + return {cos.back()}; + + /* In contrast to the read case, we need to be a bit more careful: + * the consistent choice might not satisfy atomicity, but we should + * keep it around to try revisits */ + while (!cos.empty()) { + g.moveStoreCOAfter(wLab, g.getEventLabel(cos.back())); + if (isExecutionValid(wLab)) + return {cos.back()}; + cos.erase(cos.end() - 1); } - return true; + moot(); + return std::nullopt; } void GenMCDriver::filterInvalidRecRfs(const ReadLabel *rLab, std::vector &rfs) @@ -1894,7 +1948,7 @@ std::optional GenMCDriver::handleThreadJoin(std::unique_ptrgetThread()) err += " (TID cannot be the same as the calling thread)"; - reportError(jLab->getPos(), VerificationError::VE_InvalidJoin, err); + reportError({jLab->getPos(), VerificationError::VE_InvalidJoin, err}); return {SVal(0)}; } @@ -1925,35 +1979,12 @@ void GenMCDriver::handleThreadFinish(std::unique_ptr eLab) moot(); } -void GenMCDriver::handleFenceLKMM(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); -} - void GenMCDriver::handleFence(std::unique_ptr fLab) { - if (llvm::isa(&*fLab)) { - handleFenceLKMM(std::move(fLab)); - return; - } - if (isExecutionDrivenByGraph(&*fLab)) return; addLabelToGraph(std::move(fLab)); - return; -} - -void GenMCDriver::handleCLFlush(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); - return; } void GenMCDriver::checkReconsiderFaiSpinloop(const MemAccessLabel *lab) @@ -1962,8 +1993,6 @@ void GenMCDriver::checkReconsiderFaiSpinloop(const MemAccessLabel *lab) auto *EE = getEE(); for (auto i = 0u; i < g.getNumThreads(); i++) { - auto &thr = EE->getThrById(i); - /* Is there any thread blocked on a potential spinloop? */ auto *eLab = llvm::dyn_cast(g.getLastThreadLabel(i)); if (!eLab) @@ -1985,7 +2014,6 @@ void GenMCDriver::checkReconsiderFaiSpinloop(const MemAccessLabel *lab) addLabelToGraph(FaiZNESpinEndLabel::create(pos)); } } - return; } std::vector GenMCDriver::getRfsApproximation(const ReadLabel *lab) @@ -2015,7 +2043,7 @@ std::vector GenMCDriver::getRfsApproximation(const ReadLabel *lab) return rfs; } -bool GenMCDriver::filterOptimizeRfs(const ReadLabel *lab, std::vector &stores) +void GenMCDriver::filterOptimizeRfs(const ReadLabel *lab, std::vector &stores) { /* Symmetry reduction */ if (getConf()->symmetryReduction) @@ -2027,12 +2055,6 @@ bool GenMCDriver::filterOptimizeRfs(const ReadLabel *lab, std::vector &st /* Keep values that do not lead to blocking */ filterValuesFromAnnotSAVER(lab, stores); - - if (!isRescheduledRead(lab->getPos())) { - if (removeCASReadIfBlocks(lab, getGraph().getEventLabel(stores.back()))) - return false; - } - return true; } void GenMCDriver::filterAtomicityViolations(const ReadLabel *rLab, std::vector &stores) @@ -2074,7 +2096,7 @@ void GenMCDriver::updateStSpaceChoices(const ReadLabel *rLab, const std::vector< choices[rLab->getStamp()] = stores; } -std::optional GenMCDriver::pickRandomRf(ReadLabel *rLab, std::vector &stores) +Event GenMCDriver::pickRandomRf(ReadLabel *rLab, std::vector &stores) { auto &g = getGraph(); @@ -2088,12 +2110,7 @@ std::optional GenMCDriver::pickRandomRf(ReadLabel *rLab, std::vectorgetPos(), stores[random]); - - if (readsUninitializedMem(rLab)) { - reportError(rLab->getPos(), VerificationError::VE_UninitializedMem); - return std::nullopt; - } - return getWriteValue(rLab->getRf(), rLab->getAccess()); + return stores[random]; } std::optional GenMCDriver::handleLoad(std::unique_ptr rLab) @@ -2107,86 +2124,59 @@ std::optional GenMCDriver::handleLoad(std::unique_ptr rLab) if (isExecutionDrivenByGraph(&*rLab)) return getReadRetValue(llvm::dyn_cast(g.getEventLabel(rLab->getPos()))); - /* First, we have to check whether the access is valid. This has to - * happen here because we may query the interpreter for this location's - * value in order to determine whether this load is going to be an RMW. - * Coherence needs to be tracked before validity is established, as - * consistency checks may be triggered if the access is invalid */ - g.trackCoherenceAtLoc(rLab->getAddr()); - if (!rLab->getAnnot()) rLab->setAnnot(EE->getCurrentAnnotConcretized()); - cacheEventLabel(&*rLab); auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(rLab))); - if (!isAccessValid(lab)) { - reportError(lab->getPos(), VerificationError::VE_AccessNonMalloc); + if (checkAccessValidity(lab) != VerificationError::VE_OK || + checkForRaces(lab) != VerificationError::VE_OK || + checkIPRValidity(lab) != VerificationError::VE_OK) return std::nullopt; /* This execution will be blocked */ - } - g.addAlloc(findAllocatingLabel(g, lab->getAddr()), lab); - if (checkForRaces(lab) != VerificationError::VE_OK) + /* Check whether the load forces us to reconsider some existing event */ + checkReconsiderFaiSpinloop(lab); + + /* If a CAS read cannot be added maximally, reschedule */ + if (!isRescheduledRead(lab->getPos()) && + removeCASReadIfBlocks(lab, g.co_max(lab->getAddr()))) return std::nullopt; + if (isRescheduledRead(lab->getPos())) + setRescheduledRead(Event::getInit()); /* Get an approximation of the stores we can read from */ auto stores = getRfsApproximation(lab); BUG_ON(stores.empty()); GENMC_DEBUG(LOG(VerbosityLevel::Debug3) << "Rfs: " << format(stores) << "\n";); - - /* Try to minimize the number of rfs */ - if (!filterOptimizeRfs(lab, stores)) - return std::nullopt; - - /* ... add an appropriate label with a random rf */ - g.changeRf(lab->getPos(), stores.back()); + filterOptimizeRfs(lab, stores); GENMC_DEBUG(LOG(VerbosityLevel::Debug3) << "Rfs (optimized): " << format(stores) << "\n";); - /* ... and make sure that the rf we end up with is consistent and respects the bound */ - if (!ensureConsistentRf(lab, stores)) - return std::nullopt; - - if (readsUninitializedMem(lab)) { - reportError(lab->getPos(), VerificationError::VE_UninitializedMem); - return std::nullopt; - } - - /* If this is the last part of barrier_wait() check whether we should block */ - auto retVal = getWriteValue(g.getEventLabel(stores.back()), lab->getAccess()); - if (llvm::isa(lab) && retVal != getBarrierInitValue(lab->getAccess())) { - blockThread(BarrierBlockLabel::create(lab->getPos().next())); - if (!getConf()->disableBAM) - return {retVal}; - } - - if (isRescheduledRead(lab->getPos())) - setRescheduledRead(Event::getInit()); - if (lab->getAnnot()) - checkIPRValidity(lab); - + std::optional rf = std::nullopt; if (inEstimationMode()) { updateStSpaceChoices(lab, stores); filterAtomicityViolations(lab, stores); - return pickRandomRf(lab, stores); + rf = pickRandomRf(lab, stores); + } else { + rf = findConsistentRf(lab, stores); + /* Push all the other alternatives choices to the Stack (many maximals for wb) */ + for (const auto &s : stores | std::views::take(stores.size() - 1)) { + auto status = false; /* MO messes with the status */ + addToWorklist(lab->getStamp(), std::make_unique( + lab->getPos(), s, status)); + } } + /* Ensured the selected rf comes from an initialized memory location */ + if (!rf.has_value() || checkInitializedMem(lab) != VerificationError::VE_OK) + return std::nullopt; + GENMC_DEBUG(LOG(VerbosityLevel::Debug2) << "--- Added load " << lab->getPos() << "\n" << getGraph();); - /* Check whether the load forces us to reconsider some existing event */ - checkReconsiderFaiSpinloop(lab); - - /* Check for races and reading from uninitialized memory */ - if (llvm::isa(lab)) - checkLockValidity(lab, stores); - if (llvm::isa(lab)) - checkBIncValidity(lab, stores); - - /* Push all the other alternatives choices to the Stack (many maximals for wb) */ - std::for_each(stores.begin(), stores.end() - 1, [&](const Event &s) { - auto status = false; /* MO messes with the status */ - addToWorklist(lab->getStamp(), - std::make_unique(lab->getPos(), s, status)); - }); + /* If this is the last part of barrier_wait() check whether we should block */ + auto retVal = getWriteValue(g.getEventLabel(*rf), lab->getAccess()); + if (llvm::isa(lab) && retVal != getBarrierInitValue(lab->getAccess())) { + blockThread(BarrierBlockLabel::create(lab->getPos().next())); + } return {retVal}; } @@ -2226,14 +2216,30 @@ std::vector GenMCDriver::getRevisitableApproximation(const WriteLabel *sL return loads; } -void GenMCDriver::pickRandomCo(WriteLabel *sLab, - const llvm::iterator_range &placesRange) +void GenMCDriver::pickRandomCo(WriteLabel *sLab, std::vector &cos) { auto &g = getGraph(); - MyDist dist(0, std::distance(placesRange.begin(), placesRange.end())); + g.addStoreToCOAfter(sLab, g.getEventLabel(cos.back())); + cos.erase(std::remove_if(cos.begin(), cos.end(), + [&](auto &s) { + g.moveStoreCOAfter(sLab, g.getEventLabel(s)); + return !isExecutionValid(sLab); + }), + cos.end()); + + /* Extensibility is not guaranteed if an RMW read is not reading maximally + * (during estimation, reads read from arbitrary places anyway). + * If that is the case, we have to ensure that estimation won't stop. */ + if (cos.empty()) { + moot(); + addToWorklist(0, std::make_unique()); + return; + } + + MyDist dist(0, cos.size() - 1); auto random = dist(estRng); - g.addStoreToCO(sLab, std::next(placesRange.begin(), (long long)random)); + g.moveStoreCOAfter(sLab, g.getEventLabel(cos[random])); } void GenMCDriver::updateStSpaceChoices(const WriteLabel *wLab, const std::vector &stores) @@ -2242,37 +2248,14 @@ void GenMCDriver::updateStSpaceChoices(const WriteLabel *wLab, const std::vector choices[wLab->getStamp()] = stores; } -void GenMCDriver::calcCoOrderings(WriteLabel *lab) +void GenMCDriver::calcCoOrderings(WriteLabel *lab, const std::vector &cos) { - /* Find all possible placings in coherence for this store. - * If appropriate, print a WW-race warning (if this moots, exploration will anyway be cut). - * Printing happens after choices are updated, to not invalidate iterators */ auto &g = getGraph(); - auto placesRange = getCoherentPlacings(lab->getAddr(), lab->getPos(), g.isRMWStore(lab)); - auto *racyWrite = placesRange.begin() != placesRange.end() ? &*placesRange.begin() - : nullptr; - if (inEstimationMode()) { - std::vector cos; - std::transform(placesRange.begin(), placesRange.end(), std::back_inserter(cos), - [&](auto &lab) { return lab.getPos(); }); - cos.push_back(Event::getBottom()); - pickRandomCo(lab, placesRange); - updateStSpaceChoices(lab, cos); - if (racyWrite) - reportWarningOnce(lab->getPos(), VerificationError::VE_WWRace, racyWrite); - return; - } - - /* We cannot place the write just before the write of an RMW or during recovery */ - for (auto &succLab : placesRange) { - if (!g.isRMWStore(succLab.getPos()) && !inRecoveryMode()) - addToWorklist(lab->getStamp(), std::make_unique( - lab->getPos(), succLab.getPos())); + for (auto &pred : cos | std::views::take(cos.size() - 1)) { + addToWorklist(lab->getStamp(), + std::make_unique(lab->getPos(), pred)); } - g.addStoreToCO(lab, placesRange.end()); - if (racyWrite) - reportWarningOnce(lab->getPos(), VerificationError::VE_WWRace, racyWrite); } void GenMCDriver::handleStore(std::unique_ptr wLab) @@ -2282,60 +2265,48 @@ void GenMCDriver::handleStore(std::unique_ptr wLab) auto &g = getGraph(); - /* If it's a valid access, track coherence for this location */ - g.trackCoherenceAtLoc(wLab->getAddr()); - if (getConf()->helper && g.isRMWStore(&*wLab)) annotateStoreHELPER(&*wLab); + if (llvm::isa(&*wLab) && wLab->getVal() == SVal(0)) + wLab->setVal(getBarrierInitValue(wLab->getAccess())); auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(wLab))); - if (!isAccessValid(lab)) { - reportError(lab->getPos(), VerificationError::VE_AccessNonMalloc); + if (checkAccessValidity(lab) != VerificationError::VE_OK || + checkInitializedMem(lab) != VerificationError::VE_OK || + checkFinalAnnotations(lab) != VerificationError::VE_OK || + checkForRaces(lab) != VerificationError::VE_OK) return; - } - g.addAlloc(findAllocatingLabel(g, lab->getAddr()), lab); - /* It is always consistent to add the store at the end of MO */ - if (llvm::isa(lab) && lab->getVal() == SVal(0)) - lab->setVal(getBarrierInitValue(lab->getAccess())); + checkReconsiderFaiSpinloop(lab); + unblockWaitingHelping(lab); + checkReconsiderReadOpts(lab); - calcCoOrderings(lab); + /* Find all possible placings in coherence for this store, and + * print a WW-race warning if appropriate (if this moots, + * exploration will anyway be cut) */ + auto cos = getCoherentPlacings(lab->getAddr(), lab->getPos(), g.isRMWStore(lab)); + if (cos.size() > 1) { + reportWarningOnce(lab->getPos(), VerificationError::VE_WWRace, + g.getEventLabel(cos[0])); + } - /* If the graph is not consistent (e.g., w/ LAPOR) stop the exploration */ - bool cons = ensureConsistentStore(lab); + std::optional co; + if (inEstimationMode()) { + pickRandomCo(lab, cos); + updateStSpaceChoices(lab, cos); + } else { + co = findConsistentCo(lab, cos); + calcCoOrderings(lab, cos); + } GENMC_DEBUG(LOG(VerbosityLevel::Debug2) << "--- Added store " << lab->getPos() << "\n" << getGraph();); - if (cons && checkForRaces(lab) != VerificationError::VE_OK) + if (inRecoveryMode() || inReplay()) return; - if (!inRecoveryMode() && !inReplay()) - calcRevisits(lab); - - if (!cons) - return; - - checkReconsiderFaiSpinloop(lab); - if (llvm::isa(lab)) - unblockWaitingHelping(); - checkReconsiderReadOpts(lab); - - /* Check for races */ - if (llvm::isa(lab)) - checkUnlockValidity(lab); - if (llvm::isa(lab)) - checkBInitValidity(lab); - checkFinalAnnotations(lab); -} - -void GenMCDriver::handleHpProtect(std::unique_ptr hpLab) -{ - if (isExecutionDrivenByGraph(&*hpLab)) - return; - - addLabelToGraph(std::move(hpLab)); + calcRevisits(lab); } SVal GenMCDriver::handleMalloc(std::unique_ptr aLab) @@ -2351,7 +2322,6 @@ SVal GenMCDriver::handleMalloc(std::unique_ptr aLab) /* Fix and add label to the graph; return the new address */ if (aLab->getAllocAddr() == SAddr()) aLab->setAllocAddr(getFreshAddr(&*aLab)); - cacheEventLabel(&*aLab); auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(aLab))); return SVal(lab->getAllocAddr().get()); } @@ -2380,30 +2350,6 @@ void GenMCDriver::handleFree(std::unique_ptr dLab) checkForRaces(lab); } -void GenMCDriver::handleRCULockLKMM(std::unique_ptr lLab) -{ - if (isExecutionDrivenByGraph(&*lLab)) - return; - - addLabelToGraph(std::move(lLab)); -} - -void GenMCDriver::handleRCUUnlockLKMM(std::unique_ptr uLab) -{ - if (isExecutionDrivenByGraph(&*uLab)) - return; - - addLabelToGraph(std::move(uLab)); -} - -void GenMCDriver::handleRCUSyncLKMM(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); -} - const MemAccessLabel *GenMCDriver::getPreviousVisibleAccessLabel(Event start) const { auto &g = getGraph(); @@ -2412,7 +2358,7 @@ const MemAccessLabel *GenMCDriver::getPreviousVisibleAccessLabel(Event start) co for (auto pos = start.prev(); pos.index > 0; --pos) { auto *lab = g.getEventLabel(pos); if (auto *rLab = llvm::dyn_cast(lab)) { - if (getConf()->helper && g.isConfirming(rLab)) + if (getConf()->helper && rLab->isConfirming()) continue; if (rLab->getRf()) { auto *wLab = llvm::dyn_cast(rLab->getRf()); @@ -2456,7 +2402,8 @@ void GenMCDriver::handleBlock(std::unique_ptr lab) if (isExecutionDrivenByGraph(&*lab)) return; - auto &g = getGraph(); + /* Call addLabelToGraph first to cache the label */ + addLabelToGraph(lab->clone()); blockThreadTryMoot(std::move(lab)); } @@ -2475,9 +2422,7 @@ std::unique_ptr GenMCDriver::getReplayView() const return v; } -void GenMCDriver::reportError(Event pos, VerificationError s, const std::string &err /* = "" */, - const EventLabel *racyLab /* = nullptr */, - bool shouldHalt /* = true */) +void GenMCDriver::reportError(const ErrorDetails &details) { auto &g = getGraph(); @@ -2492,14 +2437,14 @@ void GenMCDriver::reportError(Event pos, VerificationError s, const std::string /* Ignore soft errors under estimation mode. * These are going to be reported later on anyway */ - if (!shouldHalt && inEstimationMode()) + if (!details.shouldHalt && inEstimationMode()) return; /* If this is an invalid access, change the RF of the offending * event to BOTTOM, so that we do not try to get its value. * Don't bother updating the views */ - auto *errLab = g.getEventLabel(pos); - if (isInvalidAccessError(s) && llvm::isa(errLab)) + auto *errLab = g.getEventLabel(details.pos); + if (isInvalidAccessError(details.type) && llvm::isa(errLab)) g.changeRf(errLab->getPos(), Event::getBottom()); /* Print a basic error message and the graph. @@ -2511,39 +2456,39 @@ void GenMCDriver::reportError(Event pos, VerificationError s, const std::string llvm::raw_string_ostream out(result.message); - out << (isHardError(s) ? "Error: " : "Warning: ") << s << "!\n"; + out << (isHardError(details.type) ? "Error: " : "Warning: ") << details.type << "!\n"; out << "Event " << errLab->getPos() << " "; - if (racyLab != nullptr) - out << "conflicts with event " << racyLab->getPos() << " "; + if (details.racyLab != nullptr) + out << "conflicts with event " << details.racyLab->getPos() << " "; out << "in graph:\n"; printGraph(true, out); /* Print error trace leading up to the violating event(s) */ if (getConf()->printErrorTrace) { printTraceBefore(errLab, out); - if (racyLab != nullptr) - printTraceBefore(racyLab, out); + if (details.racyLab != nullptr) + printTraceBefore(details.racyLab, out); } /* Print the specific error message */ - if (!err.empty()) - out << err << "\n"; + if (!details.msg.empty()) + out << details.msg << "\n"; /* Dump the graph into a file (DOT format) */ if (!getConf()->dotFile.empty()) - dotPrintToFile(getConf()->dotFile, errLab, racyLab); + dotPrintToFile(getConf()->dotFile, errLab, details.racyLab); getEE()->restoreState(std::move(iState)); - if (shouldHalt) - halt(s); + if (details.shouldHalt) + halt(details.type); } bool GenMCDriver::reportWarningOnce(Event pos, VerificationError wcode, const EventLabel *racyLab /* = nullptr */) { /* Helper function to determine whether the warning should be treated as an error */ - auto isHardError = [&](auto &wcode) { + auto shouldUpgradeWarning = [&](auto &wcode) { if (wcode != VerificationError::VE_WWRace) return std::make_pair(false, ""s); if (!getConf()->symmetryReduction && !getConf()->ipr) @@ -2551,7 +2496,7 @@ bool GenMCDriver::reportWarningOnce(Event pos, VerificationError wcode, auto &g = getGraph(); auto *lab = g.getEventLabel(pos); - auto hardError = + auto upgrade = (getConf()->symmetryReduction && std::any_of(g.getThreadList().begin(), g.getThreadList().end(), [&](auto &thr) { @@ -2565,27 +2510,30 @@ bool GenMCDriver::reportWarningOnce(Event pos, VerificationError wcode, return rLab && rLab->getAnnot(); })); auto [cause, cli] = - getConf()->ipr ? std::make_pair("in-place revisiting"s, "-disable-ipr"s) - : std::make_pair("symmetry reduction"s, "-disable-sr"s); - auto msg = hardError ? ("Warning treated as an error due to " + cause + - ".\n" - "You can use " + - cli + " to disable these features."s) - : ""s; - return std::make_pair(hardError, msg); + getConf()->ipr + ? std::make_pair("in-place revisiting (IPR)"s, "-disable-ipr"s) + : std::make_pair("symmetry reduction (SR)"s, "-disable-sr"s); + auto msg = "Unordered writes do not constitute a bug per se, though they often " + "indicate faulty design.\n" + + (upgrade ? ("This warning is treated as an error due to " + cause + + ".\n" + "You can use " + + cli + " to disable these features."s) + : ""s); + return std::make_pair(upgrade, msg); }; /* If the warning has been seen before, only report it if it's an error */ - auto [hardError, msg] = isHardError(wcode); + auto [upgradeWarning, msg] = shouldUpgradeWarning(wcode); auto &knownWarnings = getResult().warnings; - if (hardError || knownWarnings.count(wcode) == 0) { - reportError(pos, wcode, msg, racyLab, hardError); + if (upgradeWarning || knownWarnings.count(wcode) == 0) { + reportError({pos, wcode, msg, racyLab, upgradeWarning}); } if (knownWarnings.count(wcode) == 0) knownWarnings.insert(wcode); if (wcode == VerificationError::VE_WWRace) getGraph().getWriteLabel(pos)->setAttr(WriteAttr::WWRacy); - return hardError; + return upgradeWarning; } bool GenMCDriver::tryOptimizeBarrierRevisits(const BIncFaiWriteLabel *sLab, @@ -2604,19 +2552,20 @@ bool GenMCDriver::tryOptimizeBarrierRevisits(const BIncFaiWriteLabel *sLab, auto bs = g.collectAllEvents([&](const EventLabel *lab) { if (!llvm::isa(lab)) return false; - auto *pLab = - llvm::dyn_cast(g.getPreviousLabel(lab->getPos().prev())); + auto *pLab = llvm::dyn_cast( + g.getPreviousLabel(g.getPreviousLabel(lab))); return pLab->getAddr() == sLab->getAddr(); }); auto unblockedLoads = std::count_if(loads.begin(), loads.end(), [&](auto &l) { - auto *nLab = llvm::dyn_cast_or_null(g.getNextLabel(l)); + auto *nLab = llvm::dyn_cast_or_null(g.getNextLabel(g.getEventLabel(l))); return !nLab; }); if (bs.size() > iVal.get() || unblockedLoads > 0) WARN_ONCE("bam-well-formed", "Execution not barrier-well-formed!\n"); std::for_each(bs.begin(), bs.end(), [&](const Event &b) { - auto *pLab = llvm::dyn_cast(g.getPreviousLabel(b.prev())); + auto *pLab = llvm::dyn_cast( + g.getPreviousLabel(g.getPreviousLabel(g.getEventLabel(b)))); BUG_ON(!pLab); unblockThread(b); g.removeLast(b.thread); @@ -2681,11 +2630,7 @@ bool GenMCDriver::removeCASReadIfBlocks(const ReadLabel *rLab, const EventLabel if (!willBeAssumeBlocked(rLab, val)) return false; - auto &g = getGraph(); - auto pos = rLab->getPos(); - auto addr = rLab->getAddr(); - g.removeLast(pos.thread); - blockThread(ReadOptBlockLabel::create(pos, addr)); + blockThread(ReadOptBlockLabel::create(rLab->getPos(), rLab->getAddr())); return true; } @@ -2709,7 +2654,7 @@ void GenMCDriver::optimizeUnconfirmedRevisits(const WriteLabel *sLab, std::vecto /* If there is already a write with the same value, report a possible ABA */ auto valid = std::count_if( - store_begin(g, sLab->getAddr()), store_end(g, sLab->getAddr()), [&](auto &wLab) { + g.co_begin(sLab->getAddr()), g.co_end(sLab->getAddr()), [&](auto &wLab) { return wLab.getPos() != sLab->getPos() && wLab.getVal() == sLab->getVal(); }); if (sLab->getAddr().isStatic() && @@ -2723,7 +2668,7 @@ void GenMCDriver::optimizeUnconfirmedRevisits(const WriteLabel *sLab, std::vecto std::remove_if(loads.begin(), loads.end(), [&](const Event &l) { auto *lab = llvm::dyn_cast(g.getEventLabel(l)); - if (!g.isConfirming(lab)) + if (!lab->isConfirming()) return false; auto sc = Event::getInit(); @@ -2762,10 +2707,10 @@ bool GenMCDriver::tryOptimizeRevBlockerAddition(const WriteLabel *sLab, std::vec auto &g = getGraph(); auto *pLab = getPreviousVisibleAccessLabel(sLab->getPos().prev()); - if (std::find_if(store_begin(g, sLab->getAddr()), store_end(g, sLab->getAddr()), + if (std::find_if(g.co_begin(sLab->getAddr()), g.co_end(sLab->getAddr()), [this, pLab, sLab](auto &lab) { return isConflictingNonRevBlocker(pLab, sLab, lab.getPos()); - }) != store_end(g, sLab->getAddr())) { + }) != g.co_end(sLab->getAddr())) { moot(); loads.clear(); return true; @@ -2884,7 +2829,7 @@ std::unique_ptr GenMCDriver::constructBackwardRevisit(const Rea /* Check whether there is a conflicting RevBlocker */ auto pending = g.getPendingRMW(sLab); - auto *pLab = llvm::dyn_cast_or_null(g.getNextLabel(pending)); + auto *pLab = llvm::dyn_cast_or_null(g.getNextLabel(g.getEventLabel(pending))); pending = (!pending.isInitializer() && pLab->hasAttr(WriteAttr::RevBlocker)) ? pending.next() : Event::getInit(); @@ -3031,7 +2976,7 @@ bool GenMCDriver::isMaximalExtension(const BackwardRevisit &r) auto &g = getGraph(); auto &v = r.getViewNoRel(); - for (const auto &lab : labels(g)) { + for (const auto &lab : g.labels()) { if ((lab.getPos() != r.getPos() && v->contains(lab.getPos())) || prefixContainsSameLoc(r, &lab)) continue; @@ -3052,14 +2997,14 @@ bool GenMCDriver::revisitModifiesGraph(const BackwardRevisit &r) const auto &v = r.getViewNoRel(); for (auto i = 0u; i < g.getNumThreads(); i++) { if (v->getMax(i) + 1 != (long)g.getThreadSize(i) && - !g.getEventLabel(Event(i, v->getMax(i) + 1))->isTerminator()) + !llvm::isa(g.getEventLabel(Event(i, v->getMax(i) + 1)))) return true; if (!getConf()->isDepTrackingModel) continue; for (auto j = 0u; j < g.getThreadSize(i); j++) { auto *lab = g.getEventLabel(Event(i, j)); if (!v->contains(lab->getPos()) && !llvm::isa(lab) && - !lab->isTerminator()) + !llvm::isa(lab)) return true; } } @@ -3089,7 +3034,7 @@ std::unique_ptr GenMCDriver::copyGraph(const BackwardRevisit *br auto *revLab = og->getReadLabel(br->getPos()); og->compressStampsAfter(revLab->getStamp()); - for (auto &lab : labels(*og)) { + for (auto &lab : og->labels()) { if (prefix.contains(lab.getPos())) lab.setRevisitStatus(false); } @@ -3102,7 +3047,7 @@ GenMCDriver::ChoiceMap GenMCDriver::createChoiceMapForCopy(const ExecutionGraph const auto &choices = getChoiceMap(); ChoiceMap result; - for (auto &lab : labels(g)) { + for (auto &lab : g.labels()) { if (!og.containsPos(lab.getPos()) || !choices.count(lab.getStamp())) continue; @@ -3188,7 +3133,8 @@ WriteLabel *GenMCDriver::completeRevisitedRMW(const ReadLabel *rLab) WriteAttr wattr = WriteAttr::None; if (auto *faiLab = llvm::dyn_cast(rLab)) { /* Need to get the rf value within the if, as rLab might be a disk op, - * and we cannot get the value in that case (but it will also not be an RMW) */ + * and we cannot get the value in that case (but it will also not be an RMW) + */ auto rfVal = getReadValue(rLab); result = getEE()->executeAtomicRMWOperation(rfVal, faiLab->getOpVal(), faiLab->getSize(), faiLab->getOp()); @@ -3205,7 +3151,7 @@ WriteLabel *GenMCDriver::completeRevisitedRMW(const ReadLabel *rLab) std::unique_ptr wLab = nullptr; #define CREATE_COUNTERPART(name) \ - case EventLabel::EL_##name##Read: \ + case EventLabel::name##Read: \ wLab = name##WriteLabel::create(rLab->getPos().next(), rLab->getOrdering(), \ rLab->getAddr(), rLab->getSize(), rLab->getType(), \ result, wattr); \ @@ -3224,15 +3170,9 @@ WriteLabel *GenMCDriver::completeRevisitedRMW(const ReadLabel *rLab) BUG(); } BUG_ON(!wLab); - cacheEventLabel(&*wLab); auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(wLab))); BUG_ON(!rLab->getRf()); - if (auto *rfLab = llvm::dyn_cast(rLab->getRf())) { - g.addStoreToCO(lab, ExecutionGraph::co_iterator(g.co_succ_begin(rfLab))); - } else { - g.addStoreToCO(lab, g.co_begin(lab->getAddr())); - } - g.addAlloc(findAllocatingLabel(g, lab->getAddr()), lab); + g.addStoreToCOAfter(lab, rLab->getRf()); return lab; } @@ -3242,8 +3182,7 @@ bool GenMCDriver::revisitWrite(const WriteForwardRevisit &ri) auto *wLab = g.getWriteLabel(ri.getPos()); BUG_ON(!wLab); - g.removeStoreFromCO(wLab); - g.addStoreToCO(wLab, ExecutionGraph::co_iterator(g.getWriteLabel(ri.getSucc()))); + g.moveStoreCOAfter(wLab, g.getEventLabel(ri.getPred())); wLab->setAddedMax(false); return calcRevisits(wLab); } @@ -3370,117 +3309,17 @@ bool GenMCDriver::restrictAndRevisit(Stamp stamp, const WorkSet::ItemT &item) return false; } -SVal GenMCDriver::handleDskRead(std::unique_ptr drLab) -{ - auto &g = getGraph(); - - if (isExecutionDrivenByGraph(&*drLab)) { - auto *rLab = llvm::dyn_cast(g.getEventLabel(drLab->getPos())); - BUG_ON(!rLab); - return getDskReadValue(rLab); - } - - /* Make the graph aware of a (potentially) new memory location */ - g.trackCoherenceAtLoc(drLab->getAddr()); - - /* Get all stores to this location from which we can read from */ - auto validStores = getRfsApproximation(&*drLab); - BUG_ON(validStores.empty()); - - /* ... and add an appropriate label with a particular rf */ - if (inRecoveryMode()) - drLab->setOrdering(llvm::AtomicOrdering::Monotonic); - auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(drLab))); - g.changeRf(lab->getPos(), validStores[0]); - - /* ... filter out all option that make the recovery invalid */ - filterInvalidRecRfs(lab, validStores); - - /* Push all the other alternatives choices to the Stack */ - for (auto it = validStores.begin() + 1; it != validStores.end(); ++it) - addToWorklist(lab->getStamp(), - std::make_unique(lab->getPos(), *it)); - return getDskWriteValue(g.getEventLabel(validStores[0]), lab->getAccess()); -} - -void GenMCDriver::handleDskWrite(std::unique_ptr wLab) -{ - if (isExecutionDrivenByGraph(&*wLab)) - return; - - auto &g = getGraph(); - - g.trackCoherenceAtLoc(wLab->getAddr()); - - /* Disk writes should always be hb-ordered */ - auto placesRange = getCoherentPlacings(wLab->getAddr(), wLab->getPos(), false); - BUG_ON(placesRange.begin() != placesRange.end()); - - /* Safe to _only_ add it at the end of MO */ - auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(wLab))); - g.addStoreToCO(lab, placesRange.end()); - - calcRevisits(lab); - return; -} - -SVal GenMCDriver::handleDskOpen(std::unique_ptr oLab) -{ - auto &g = getGraph(); - - if (isExecutionDrivenByGraph(&*oLab)) { - auto *lab = llvm::dyn_cast(g.getEventLabel(oLab->getPos())); - BUG_ON(!lab); - return lab->getFd(); - } - - /* We get a fresh file descriptor for this open() */ - auto fd = getFreshFd(); - ERROR_ON(fd == -1, "Too many calls to open()!\n"); - - oLab->setFd(SVal(fd)); - auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(oLab))); - return lab->getFd(); -} - -void GenMCDriver::handleDskFsync(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); - return; -} - -void GenMCDriver::handleDskSync(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); - return; -} - -void GenMCDriver::handleDskPbarrier(std::unique_ptr fLab) -{ - if (isExecutionDrivenByGraph(&*fLab)) - return; - - addLabelToGraph(std::move(fLab)); - return; -} - bool GenMCDriver::handleHelpingCas(std::unique_ptr hLab) { if (isExecutionDrivenByGraph(&*hLab)) return true; - /* Before adding it to the graph, ensure that the helped CAS exists */ - if (!checkHelpingCasCondition(&*hLab)) { - blockThread(HelpedCASBlockLabel::create(hLab->getPos())); + /* Ensure that the helped CAS exists */ + auto *lab = llvm::dyn_cast(addLabelToGraph(std::move(hLab))); + if (!checkHelpingCasCondition(lab)) { + blockThread(HelpedCASBlockLabel::create(lab->getPos())); return false; } - addLabelToGraph(std::move(hLab)); return true; } @@ -3491,7 +3330,7 @@ bool GenMCDriver::handleOptional(std::unique_ptr lab) if (isExecutionDrivenByGraph(&*lab)) return llvm::dyn_cast(g.getEventLabel(lab->getPos()))->isExpanded(); - if (std::any_of(label_begin(g), label_end(g), [&](auto &lab) { + if (std::any_of(g.label_begin(), g.label_end(), [&](auto &lab) { auto *oLab = llvm::dyn_cast(&lab); return oLab && !oLab->isExpandable(); })) @@ -3505,15 +3344,6 @@ bool GenMCDriver::handleOptional(std::unique_ptr lab) return false; /* should not be expanded yet */ } -void GenMCDriver::handleLoopBegin(std::unique_ptr bLab) -{ - if (isExecutionDrivenByGraph(&*bLab)) - return; - - addLabelToGraph(std::move(bLab)); - return; -} - bool GenMCDriver::isWriteEffectful(const WriteLabel *wLab) { auto &g = getGraph(); @@ -3566,7 +3396,8 @@ void GenMCDriver::handleSpinStart(std::unique_ptr lab) /* Check whether we can detect some spinloop dynamically */ auto *lbLab = g.getPreviousLabelST( stLab, [](const EventLabel *lab) { return llvm::isa(lab); }); - /* If we did not find a loop-begin, this a manual instrumentation(?); report to user */ + /* If we did not find a loop-begin, this a manual instrumentation(?); report to user + */ ERROR_ON(!lbLab, "No loop-beginning found!\n"); auto *pLab = g.getPreviousLabelST(stLab, [lbLab](const EventLabel *lab) { @@ -3582,9 +3413,7 @@ void GenMCDriver::handleSpinStart(std::unique_ptr lab) return; /* found event w/ side-effects */ } /* Spinloop detected */ - auto stPos = stLab->getPos(); - g.removeLast(stPos.thread); - blockThreadTryMoot(SpinloopBlockLabel::create(stPos)); + blockThreadTryMoot(SpinloopBlockLabel::create(stLab->getPos())); } bool GenMCDriver::areFaiZNEConstraintsSat(const FaiZNESpinEndLabel *lab) @@ -3609,7 +3438,7 @@ bool GenMCDriver::areFaiZNEConstraintsSat(const FaiZNESpinEndLabel *lab) /* All stores in the RMW chain need to be read from at most 1 read, * and there need to be no other stores that are not hb-before lab */ - for (auto &lab : labels(g)) { + for (auto &lab : g.labels()) { if (auto *mLab = llvm::dyn_cast(&lab)) { if (mLab->getAddr() == wLab->getAddr() && !llvm::isa(mLab) && !llvm::isa(mLab) && @@ -3629,12 +3458,8 @@ void GenMCDriver::handleFaiZNESpinEnd(std::unique_ptr lab) return; auto *zLab = llvm::dyn_cast(addLabelToGraph(std::move(lab))); - if (areFaiZNEConstraintsSat(&*zLab)) { - auto pos = zLab->getPos(); - g.removeLast(pos.thread); - blockThreadTryMoot(FaiZNEBlockLabel::create(pos)); - } - return; + if (areFaiZNEConstraintsSat(zLab)) + blockThreadTryMoot(FaiZNEBlockLabel::create(zLab->getPos())); } void GenMCDriver::handleLockZNESpinEnd(std::unique_ptr lab) @@ -3642,7 +3467,14 @@ void GenMCDriver::handleLockZNESpinEnd(std::unique_ptr lab) if (isExecutionDrivenByGraph(&*lab)) return; - blockThreadTryMoot(LockZNEBlockLabel::create(lab->getPos())); + auto *zLab = addLabelToGraph(std::move(lab)); + blockThreadTryMoot(LockZNEBlockLabel::create(zLab->getPos())); +} + +void GenMCDriver::handleDummy(std::unique_ptr lab) +{ + if (!isExecutionDrivenByGraph(&*lab)) + addLabelToGraph(std::move(lab)); } /************************************************************ @@ -3717,12 +3549,7 @@ void GenMCDriver::printGraph(bool printMetadata /* false */, { auto &g = getGraph(); LabelPrinter printer([this](const SAddr &saddr) { return getVarName(saddr); }, - [this](const ReadLabel &lab) { - return llvm::isa(&lab) - ? getDskReadValue( - llvm::dyn_cast(&lab)) - : getReadValue(&lab); - }); + [this](const ReadLabel &lab) { return getReadValue(&lab); }); /* Print the graph */ for (auto i = 0u; i < g.getNumThreads(); i++) { @@ -3762,7 +3589,7 @@ void GenMCDriver::printGraph(bool printMetadata /* false */, } auto *wLab = &*g.co_begin(locIt->first); s << getVarName(wLab->getAddr()) << ": [ "; - for (const auto &w : stores(g, locIt->first)) + for (const auto &w : g.co(locIt->first)) s << w << " "; s << "]\n"; } @@ -3778,12 +3605,7 @@ void GenMCDriver::dotPrintToFile(const std::string &filename, const EventLabel * std::ofstream fout(filename); llvm::raw_os_ostream ss(fout); DotPrinter printer([this](const SAddr &saddr) { return getVarName(saddr); }, - [this](const ReadLabel &lab) { - return llvm::isa(&lab) - ? getDskReadValue( - llvm::dyn_cast(&lab)) - : getReadValue(&lab); - }); + [this](const ReadLabel &lab) { return getReadValue(&lab); }); auto before = getPrefixView(errLab).clone(); if (confLab) diff --git a/src/GenMCDriver.hpp b/src/Verification/GenMCDriver.hpp similarity index 87% rename from src/GenMCDriver.hpp rename to src/Verification/GenMCDriver.hpp index 7e3b864..101eb6f 100644 --- a/src/GenMCDriver.hpp +++ b/src/Verification/GenMCDriver.hpp @@ -18,17 +18,17 @@ * Author: Michalis Kokologiannakis */ -#ifndef __GENMC_DRIVER_HPP__ -#define __GENMC_DRIVER_HPP__ - -#include "Config.hpp" -#include "DepInfo.hpp" -#include "EventLabel.hpp" -#include "ExecutionGraph.hpp" -#include "SAddrAllocator.hpp" -#include "Trie.hpp" -#include "VerificationError.hpp" -#include "WorkSet.hpp" +#ifndef GENMC_GENMC_DRIVER_HPP +#define GENMC_GENMC_DRIVER_HPP + +#include "ADT/Trie.hpp" +#include "Config/Config.hpp" +#include "ExecutionGraph/DepInfo.hpp" +#include "ExecutionGraph/EventLabel.hpp" +#include "ExecutionGraph/ExecutionGraph.hpp" +#include "Support/SAddrAllocator.hpp" +#include "Verification/VerificationError.hpp" +#include "Verification/WorkSet.hpp" #include #include @@ -39,6 +39,7 @@ #include #include #include +#include #include namespace llvm { @@ -131,6 +132,22 @@ class GenMCDriver { ~State(); }; + /** Details for an error to be reported */ + struct ErrorDetails { + ErrorDetails() = default; + ErrorDetails(Event pos, VerificationError r, std::string err = std::string(), + const EventLabel *racyLab = nullptr, bool shouldHalt = true) + : pos(pos), type(r), msg(std::move(err)), racyLab(racyLab), + shouldHalt(shouldHalt) + {} + + Event pos{}; + VerificationError type{}; + std::string msg{}; + const EventLabel *racyLab{}; + bool shouldHalt = true; + }; + private: struct Execution; @@ -189,49 +206,44 @@ class GenMCDriver { /*** Instruction-related actions ***/ + /* A thread has just finished execution, nothing for the interpreter */ + void handleThreadFinish(std::unique_ptr eLab); + + /* A thread has terminated abnormally */ + void handleThreadKill(std::unique_ptr lab); + + /* This method blocks the current thread */ + void handleBlock(std::unique_ptr bLab); + /* Returns the value this load reads */ std::optional handleLoad(std::unique_ptr rLab); - /* A function modeling a write to disk has been interpreted. - * Returns the value read */ - SVal handleDskRead(std::unique_ptr rLab); - /* A store has been interpreted, nothing for the interpreter */ void handleStore(std::unique_ptr wLab); - /* A function modeling a write to disk has been interpreted */ - void handleDskWrite(std::unique_ptr wLab); - - /* A helping CAS operation has been interpreter. - * Returns whether the helped CAS is present. */ - bool handleHelpingCas(std::unique_ptr hLab); - - /* A function modeling the beginning of the opening of a file. - * The interpreter will get back the file descriptor */ - SVal handleDskOpen(std::unique_ptr oLab); + /* A fence has been interpreted, nothing for the interpreter */ + void handleFence(std::unique_ptr fLab); - /* An fsync() operation has been interpreted */ - void handleDskFsync(std::unique_ptr fLab); + /* Returns an appropriate result for malloc() */ + SVal handleMalloc(std::unique_ptr aLab); - /* A sync() operation has been interpreted */ - void handleDskSync(std::unique_ptr fLab); + /* A call to free() has been interpreted, nothing for the intepreter */ + void handleFree(std::unique_ptr dLab); - /* A call to __VERIFIER_pbarrier() has been interpreted */ - void handleDskPbarrier(std::unique_ptr fLab); + /* Returns the TID of the newly created thread */ + int handleThreadCreate(std::unique_ptr tcLab); - /* A fence has been interpreted, nothing for the interpreter */ - void handleFence(std::unique_ptr fLab); + /* Returns an appropriate result for pthread_join() */ + std::optional handleThreadJoin(std::unique_ptr jLab); - /* A cache line flush has been interpreted, nothing for the interpreter */ - void handleCLFlush(std::unique_ptr fLab); + /* A helping CAS operation has been interpreter. + * Returns whether the helped CAS is present. */ + bool handleHelpingCas(std::unique_ptr hLab); /* A call to __VERIFIER_opt_begin() has been interpreted. * Returns whether the block should expand */ bool handleOptional(std::unique_ptr lab); - /* A call to __VERIFIER_loop_begin() has been interpreted */ - void handleLoopBegin(std::unique_ptr lab); - /* A call to __VERIFIER_spin_start() has been interpreted */ void handleSpinStart(std::unique_ptr lab); @@ -241,39 +253,12 @@ class GenMCDriver { /* A call to __VERIFIER_lockZNE_spin_end() has been interpreted */ void handleLockZNESpinEnd(std::unique_ptr lab); - /* A thread has terminated abnormally */ - void handleThreadKill(std::unique_ptr lab); - - /* Returns the TID of the newly created thread */ - int handleThreadCreate(std::unique_ptr tcLab); - - /* Returns an appropriate result for pthread_join() */ - std::optional handleThreadJoin(std::unique_ptr jLab); - - /* A thread has just finished execution, nothing for the interpreter */ - void handleThreadFinish(std::unique_ptr eLab); - - /* __VERIFIER_hp_protect() has been called */ - void handleHpProtect(std::unique_ptr hpLab); - - /* Returns an appropriate result for malloc() */ - SVal handleMalloc(std::unique_ptr aLab); - - /* A call to free() has been interpreted, nothing for the intepreter */ - void handleFree(std::unique_ptr dLab); - - /* This method blocks the current thread */ - void handleBlock(std::unique_ptr bLab); - - /* LKMM: Handle RCU functions */ - void handleRCULockLKMM(std::unique_ptr lab); - void handleRCUUnlockLKMM(std::unique_ptr lab); - void handleRCUSyncLKMM(std::unique_ptr lab); + /* A generic helper for dummy events */ + void handleDummy(std::unique_ptr lab); /* This method either blocks the offending thread (e.g., if the * execution is invalid), or aborts the exploration */ - void reportError(Event pos, VerificationError r, const std::string &err = std::string(), - const EventLabel *racyLab = nullptr, bool shouldHalt = true); + void reportError(const ErrorDetails &details); /* Helper that reports an unreported warning only if it hasn't reported before. * Returns true if the warning should be treated as an error according to the config. */ @@ -338,10 +323,6 @@ class GenMCDriver { /* Returns the value written by a disk write */ SVal getDskWriteValue(const EventLabel *wLab, const AAccess &a); - SVal getDskWriteValue(const DskWriteLabel *wLab) - { - return getDskWriteValue(wLab, wLab->getAccess()); - } /* Returns the value read by a read */ SVal getReadValue(const ReadLabel *rLab) @@ -349,12 +330,6 @@ class GenMCDriver { return getWriteValue(rLab->getRf(), rLab->getAccess()); } - /* Returns the value read by a disk read */ - SVal getDskReadValue(const DskReadLabel *rLab) - { - return getDskWriteValue(rLab->getRf(), rLab->getAccess()); - } - /* Returns the value returned by the terminated thread */ SVal getJoinValue(const ThreadJoinLabel *jLab) const; @@ -407,9 +382,12 @@ class GenMCDriver { /* Liveness: Checks whether a spin-blocked thread reads co-maximal values */ bool threadReadsMaximal(int tid); - /* Liveness: Calls visitError() if there is a liveness violation */ + /* Liveness: Reports an error on liveness violations */ void checkLiveness(); + /* Reports an error if there is unfreed memory */ + void checkUnfreedMemory(); + /* Returns true if E is maximal in ADDR at P*/ bool isCoMaximal(SAddr addr, Event e, bool checkCache = false); @@ -516,7 +494,8 @@ class GenMCDriver { * chosen policy */ bool scheduleNormal(); - /* Blocks thread with BLAB (needs to be maximal) */ + /* Blocks thread with BLAB. BLAB needs to either replace + * the last label or be maximal */ void blockThread(std::unique_ptr bLab); /* Blocks thread at POS with type T. Tries to moot afterward */ @@ -534,35 +513,22 @@ class GenMCDriver { /* Resets the prioritization scheme */ void resetThreadPrioritization(); - /* Returns whether LAB accesses a valid location. */ - bool isAccessValid(const MemAccessLabel *lab) const; + /* If LAB accesses a valid location, reports an error */ + VerificationError checkAccessValidity(const MemAccessLabel *lab); - /* Performs POSIX checks whenever a lock event is added. - * Given its list of possible rfs, makes sure it cannot read - * from a destroyed lock. - * Appropriately calls visitErro() and terminates */ - void checkLockValidity(const ReadLabel *rLab, const std::vector &rfs); + /* If LAB accesses an uninitialized location, reports an error */ + VerificationError checkInitializedMem(const ReadLabel *lab); - /* Performs POSIX checks whenever an unlock event is added. - * Appropriately calls visitError() and terminates */ - void checkUnlockValidity(const WriteLabel *wLab); + /* If LAB accesses improperly initialized memory, reports an error */ + VerificationError checkInitializedMem(const WriteLabel *lab); - /* Perfoms POSIX checks whenever a barrier_init event is added. - Appropriately calls visitError() and terminates */ - void checkBInitValidity(const WriteLabel *wLab); - - /* Perfoms POSIX checks whenever a barrier_wait event is added. - Appropriately calls visitError() and terminates */ - void checkBIncValidity(const ReadLabel *rLab, const std::vector &rfs); + /* If LAB is an IPR read in a location with WW-races, reports an error */ + VerificationError checkIPRValidity(const ReadLabel *rLab); /* Checks whether final annotations are used properly in a program: * if there are more than one stores annotated as final at the time WLAB - * is added, visitError() is called */ - void checkFinalAnnotations(const WriteLabel *wLab); - - /* Checks whether the IPR optimization is valid (i.e., no WW-races), - * and reports an error if it's not. Returns the validity result */ - void checkIPRValidity(const ReadLabel *rLab); + * is added, reports an error */ + VerificationError checkFinalAnnotations(const WriteLabel *wLab); /* Returns true if the exploration is guided by a graph */ bool isExecutionDrivenByGraph(const EventLabel *lab); @@ -586,11 +552,10 @@ class GenMCDriver { EventLabel *addLabelToGraph(std::unique_ptr lab); /* Est: Picks (and sets) a random RF among some possible options */ - std::optional pickRandomRf(ReadLabel *rLab, std::vector &stores); + Event pickRandomRf(ReadLabel *rLab, std::vector &stores); /* Est: Picks (and sets) a random CO among some possible options */ - void pickRandomCo(WriteLabel *sLab, - const llvm::iterator_range &coRange); + void pickRandomCo(WriteLabel *sLab, std::vector &cos); /* BAM: Tries to optimize barrier-related revisits */ bool tryOptimizeBarrierRevisits(const BIncFaiWriteLabel *sLab, std::vector &loads); @@ -660,7 +625,7 @@ class GenMCDriver { /* Calculates all possible coherence placings for SLAB and * pushes them to the worklist. */ - void calcCoOrderings(WriteLabel *sLab); + void calcCoOrderings(WriteLabel *sLab, const std::vector &cos); /* Calculates revisit options and pushes them to the worklist. * Returns true if the current exploration should continue */ @@ -701,26 +666,23 @@ class GenMCDriver { /* Given a list of stores that it is consistent to read-from, * filters out options that can be skipped (according to the conf), * and determines the order in which these options should be explored */ - bool filterOptimizeRfs(const ReadLabel *lab, std::vector &stores); + void filterOptimizeRfs(const ReadLabel *lab, std::vector &stores); bool isExecutionValid(const EventLabel *lab) { return isSymmetryOK(lab) && isConsistent(lab) && !partialExecutionExceedsBound(); } - /* Removes rfs from "rfs" until a consistent option for rLab is found, - * if that is dictated by the CLI options */ - bool ensureConsistentRf(const ReadLabel *rLab, std::vector &rfs); + /* Removes rfs from RFS until a consistent option for RLAB is found */ + std::optional findConsistentRf(const ReadLabel *rLab, std::vector &rfs); + + /* Remove cos from COS until a consistent option for WLAB is found */ + std::optional findConsistentCo(WriteLabel *wLab, std::vector &cos); /* Checks whether the addition of WLAB creates an atomicity violation. * If so, returns false and moots the execution if possible. */ bool checkAtomicity(const WriteLabel *wLab); - /* Makes sure that the current graph is consistent, if that is dictated - * by the CLI options. Since that is not always the case for stores - * (e.g., w/ LAPOR), it returns whether it is the case or not */ - bool ensureConsistentStore(const WriteLabel *wLab); - /* Helper: Annotates a store as RevBlocker, if possible */ void annotateStoreHELPER(WriteLabel *wLab); @@ -770,7 +732,7 @@ class GenMCDriver { void handleFenceLKMM(std::unique_ptr fLab); /* Helper: Wake up any threads blocked on a helping CAS */ - void unblockWaitingHelping(); + void unblockWaitingHelping(const WriteLabel *lab); bool writesBeforeHelpedContainedInView(const HelpedCasReadLabel *lab, const View &view); @@ -872,7 +834,7 @@ class GenMCDriver { /* Returns true if the current graph is consistent when E is added */ virtual bool isConsistent(const EventLabel *lab) const = 0; - virtual bool isRecoveryValid(const EventLabel *lab) const = 0; + virtual bool isRecoveryValid(const EventLabel *lab) const { return true; } virtual VerificationError checkErrors(const EventLabel *lab, const EventLabel *&race) const = 0; virtual std::vector @@ -881,8 +843,7 @@ class GenMCDriver { virtual std::vector getCoherentRevisits(const WriteLabel *sLab, const VectorClock &pporf) = 0; virtual std::vector getCoherentStores(SAddr addr, Event read) = 0; - virtual llvm::iterator_range - getCoherentPlacings(SAddr addr, Event read, bool isRMW) = 0; + virtual std::vector getCoherentPlacings(SAddr addr, Event read, bool isRMW) = 0; virtual bool isDepTracking() const = 0; @@ -963,4 +924,4 @@ class GenMCDriver { MyRNG estRng; }; -#endif /* __GENMC_DRIVER_HPP__ */ +#endif /* GENMC_GENMC_DRIVER_HPP */ diff --git a/src/Revisit.cpp b/src/Verification/Revisit.cpp similarity index 97% rename from src/Revisit.cpp rename to src/Verification/Revisit.cpp index 0cda748..854f50c 100644 --- a/src/Revisit.cpp +++ b/src/Verification/Revisit.cpp @@ -56,7 +56,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Revisit &item) } case Revisit::RV_FRevMO: { auto &mi = static_cast(item); - s << mi.getKind() << "(" << mi.getPos() << ": " << mi.getSucc() << ")"; + s << mi.getKind() << "(" << mi.getPos() << ": " << mi.getPred() << ")"; break; } case Revisit::RV_FRevOpt: { diff --git a/src/Revisit.hpp b/src/Verification/Revisit.hpp similarity index 96% rename from src/Revisit.hpp rename to src/Verification/Revisit.hpp index 5b19fe4..71fd099 100644 --- a/src/Revisit.hpp +++ b/src/Verification/Revisit.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __REVISIT_HPP__ -#define __REVISIT_HPP__ +#ifndef GENMC_REVISIT_HPP +#define GENMC_REVISIT_HPP -#include "EventLabel.hpp" +#include "ExecutionGraph/EventLabel.hpp" class ReadRevisit; @@ -146,19 +146,19 @@ class ReadForwardRevisit : public ForwardRevisit, public ReadRevisit { class WriteForwardRevisit : public ForwardRevisit { protected: - WriteForwardRevisit(Kind k, Event p, Event moSucc) : ForwardRevisit(k, p), moSucc(moSucc) {} + WriteForwardRevisit(Kind k, Event p, Event moPred) : ForwardRevisit(k, p), moPred(moPred) {} public: - WriteForwardRevisit(Event p, Event moSucc) : WriteForwardRevisit(RV_FRevMO, p, moSucc) {} + WriteForwardRevisit(Event p, Event moPred) : WriteForwardRevisit(RV_FRevMO, p, moPred) {} - /* Returns the new MO successor of the event for which + /** Returns the new MO predecessor of the event for which * we are exploring alternative exploration options */ - Event getSucc() const { return moSucc; } + Event getPred() const { return moPred; } static bool classof(const Revisit *item) { return item->getKind() == RV_FRevMO; } private: - Event moSucc; + Event moPred; }; /* @@ -372,4 +372,4 @@ template struct cast_convert_val errorList = { {SystemError::SE_EPERM, "Operation not permitted"}, @@ -50,7 +50,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const VerificationError &st) case VerificationError::VE_RaceNotAtomic: return s << "Non-atomic race"; case VerificationError::VE_WWRace: - return s << "Write-write race"; + return s << "Unordered writes"; + case VerificationError::VE_UnfreedMemory: + return s << "Unfreed memory"; case VerificationError::VE_RaceFreeMalloc: return s << "Malloc-free race"; case VerificationError::VE_FreeNonMalloc: diff --git a/src/VerificationError.hpp b/src/Verification/VerificationError.hpp similarity index 88% rename from src/VerificationError.hpp rename to src/Verification/VerificationError.hpp index 53ca334..e6645e1 100644 --- a/src/VerificationError.hpp +++ b/src/Verification/VerificationError.hpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#ifndef __VERIFICATION_ERROR_HPP__ -#define __VERIFICATION_ERROR_HPP__ +#ifndef GENMC_VERIFICATION_ERROR_HPP +#define GENMC_VERIFICATION_ERROR_HPP -#include "Error.hpp" +#include "Support/Error.hpp" #include #include @@ -46,12 +46,15 @@ enum class SystemError { /* Different errors that might be encountered during verification. * Public to enable the interpreter utilize it */ enum class VerificationError { + VE_NonErrorBegin, VE_OK, + VE_WWRace, + VE_UnfreedMemory, + VE_NonErrorLast, VE_Safety, VE_Recovery, VE_Liveness, VE_RaceNotAtomic, - VE_WWRace, VE_RaceFreeMalloc, VE_FreeNonMalloc, VE_DoubleFree, @@ -76,7 +79,8 @@ enum class VerificationError { inline bool isHardError(VerificationError err) { - return err != VerificationError::VE_OK && err != VerificationError::VE_WWRace; + return !(err >= VerificationError::VE_NonErrorBegin && + err <= VerificationError::VE_NonErrorLast); } /* For compilers that do not have a recent enough lib{std}c++ */ @@ -97,4 +101,4 @@ extern const std::unordered_map */ -#ifndef __WORK_SET_HPP__ -#define __WORK_SET_HPP__ +#ifndef GENMC_WORK_SET_HPP +#define GENMC_WORK_SET_HPP -#include "EventLabel.hpp" -#include "Revisit.hpp" +#include "Verification/Revisit.hpp" #include #include #include @@ -74,4 +73,4 @@ class WorkSet { WorkSetT wset_; }; -#endif /* __WORK_SET_HPP__ */ +#endif /* GENMC_WORK_SET_HPP */ diff --git a/src/main.cpp b/src/main.cpp index d7cccc3..c89b5c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,10 +18,10 @@ * Author: Michalis Kokologiannakis */ -#include "Config.hpp" -#include "DriverFactory.hpp" -#include "Error.hpp" -#include "LLVMModule.hpp" +#include "Config/Config.hpp" +#include "Static/LLVMModule.hpp" +#include "Support/Error.hpp" +#include "Verification/DriverFactory.hpp" #include "config.h" #include @@ -134,7 +134,7 @@ void printVerificationResults(const std::shared_ptr &conf, PRINT(VerbosityLevel::Error) << res.message; PRINT(VerbosityLevel::Error) << (res.status == VerificationError::VE_OK - ? "*** Verification complete. No errors were detected.\n" + ? "*** Verification complete.\nNo errors were detected.\n" : "*** Verification unsuccessful.\n"); PRINT(VerbosityLevel::Error) << "Number of complete executions explored: " << res.explored; diff --git a/tests/correct/data-structures/ms-queue/my_queue.c b/tests/correct/data-structures/ms-queue/my_queue.c index 1dca845..f022f0f 100644 --- a/tests/correct/data-structures/ms-queue/my_queue.c +++ b/tests/correct/data-structures/ms-queue/my_queue.c @@ -24,8 +24,6 @@ static unsigned int free_lists[MAX_THREADS][MAX_FREELIST]; -void __VERIFIER_assume(int); - /* Search this thread's free list for a "new" node */ static unsigned int new_node() { diff --git a/tests/correct/data-structures/ms-queue/variants/main0.c b/tests/correct/data-structures/ms-queue/variants/main0.c index c36f879..9a5e482 100644 --- a/tests/correct/data-structures/ms-queue/variants/main0.c +++ b/tests/correct/data-structures/ms-queue/variants/main0.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../main.c" diff --git a/tests/correct/data-structures/qspinlock/fake.h b/tests/correct/data-structures/qspinlock/fake.h index d26cb2b..ac01307 100644 --- a/tests/correct/data-structures/qspinlock/fake.h +++ b/tests/correct/data-structures/qspinlock/fake.h @@ -23,6 +23,7 @@ #include #include +#include // asm/qspinlock.h uses bool #include "ordering.h" /* Stub some compiler directives */ @@ -41,12 +42,6 @@ #define EXPORT_SYMBOL(sym) /* Various data types */ -typedef _Bool bool; - -enum { - false = 0, - true = 1 -}; typedef int8_t s8; typedef uint8_t u8; diff --git a/tests/correct/data-structures/seqlock-atomic/fake.h b/tests/correct/data-structures/seqlock-atomic/fake.h index ab61059..d60bf0b 100644 --- a/tests/correct/data-structures/seqlock-atomic/fake.h +++ b/tests/correct/data-structures/seqlock-atomic/fake.h @@ -41,12 +41,6 @@ #define EXPORT_SYMBOL(sym) /* Various data types */ -typedef _Bool bool; - -enum { - false = 0, - true = 1 -}; typedef int8_t s8; typedef uint8_t u8; diff --git a/tests/correct/data-structures/seqlock/fake.h b/tests/correct/data-structures/seqlock/fake.h index 965e895..53d2609 100644 --- a/tests/correct/data-structures/seqlock/fake.h +++ b/tests/correct/data-structures/seqlock/fake.h @@ -41,13 +41,6 @@ #define EXPORT_SYMBOL(sym) /* Various data types */ -typedef _Bool bool; - -enum { - false = 0, - true = 1 -}; - typedef int8_t s8; typedef uint8_t u8; typedef int16_t s16; diff --git a/tests/correct/infr/malloc-unfreed/expected.imm.mo.in b/tests/correct/infr/malloc-unfreed/expected.imm.mo.in new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/correct/infr/malloc-unfreed/expected.imm.mo.in @@ -0,0 +1 @@ +1 diff --git a/tests/correct/infr/malloc-unfreed/expected.rc11.mo.in b/tests/correct/infr/malloc-unfreed/expected.rc11.mo.in new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/correct/infr/malloc-unfreed/expected.rc11.mo.in @@ -0,0 +1 @@ +1 diff --git a/tests/correct/infr/malloc-unfreed/expected.sc.mo.in b/tests/correct/infr/malloc-unfreed/expected.sc.mo.in new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/correct/infr/malloc-unfreed/expected.sc.mo.in @@ -0,0 +1 @@ +1 diff --git a/tests/correct/infr/malloc-unfreed/variants/malloc-unfreed.c b/tests/correct/infr/malloc-unfreed/variants/malloc-unfreed.c new file mode 100644 index 0000000..ec14139 --- /dev/null +++ b/tests/correct/infr/malloc-unfreed/variants/malloc-unfreed.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include +#include + +int main() +{ + void *a = malloc(sizeof(int)); + /* printf("addr: %p\n", a); */ + + /* should produce a warning about unfreed memory */ + return 0; +} diff --git a/tests/correct/litmus/WWR+2WR/variants/wwr+2wr0.c b/tests/correct/litmus/WWR+2WR/variants/wwr+2wr0.c index 3e26809..f0985b4 100644 --- a/tests/correct/litmus/WWR+2WR/variants/wwr+2wr0.c +++ b/tests/correct/litmus/WWR+2WR/variants/wwr+2wr0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wwr+2wr.c" diff --git a/tests/correct/litmus/WWR+2WR/wwr+2wr.c b/tests/correct/litmus/WWR+2WR/wwr+2wr.c index 68db051..89193fa 100644 --- a/tests/correct/litmus/WWR+2WR/wwr+2wr.c +++ b/tests/correct/litmus/WWR+2WR/wwr+2wr.c @@ -1,5 +1,3 @@ -void __VERIFIER_assume(int); - atomic_int x; atomic_int y; atomic_int z; diff --git a/tests/correct/litmus/assume-ctrl/assume-ctrl.c b/tests/correct/litmus/assume-ctrl/assume-ctrl.c index 7e9fe49..03fc9aa 100644 --- a/tests/correct/litmus/assume-ctrl/assume-ctrl.c +++ b/tests/correct/litmus/assume-ctrl/assume-ctrl.c @@ -27,8 +27,6 @@ atomic_int x; atomic_int y; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { __VERIFIER_assume(2 > atomic_load_explicit(&y, memory_order_relaxed) || diff --git a/tests/correct/litmus/assume-ctrl/variants/assume-ctrl0.c b/tests/correct/litmus/assume-ctrl/variants/assume-ctrl0.c index b25432a..135fd26 100644 --- a/tests/correct/litmus/assume-ctrl/variants/assume-ctrl0.c +++ b/tests/correct/litmus/assume-ctrl/variants/assume-ctrl0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../assume-ctrl.c" diff --git a/tests/correct/litmus/psc-ar/expected.imm.mo.in b/tests/correct/litmus/psc-ar/expected.imm.mo.in index d00491f..573541a 100644 --- a/tests/correct/litmus/psc-ar/expected.imm.mo.in +++ b/tests/correct/litmus/psc-ar/expected.imm.mo.in @@ -1 +1 @@ -1 +0 diff --git a/tests/correct/litmus/psc-ar/psc-ar.c b/tests/correct/litmus/psc-ar/psc-ar.c index 4886293..87a0c52 100644 --- a/tests/correct/litmus/psc-ar/psc-ar.c +++ b/tests/correct/litmus/psc-ar/psc-ar.c @@ -1,5 +1,3 @@ -void __VERIFIER_assume(int); - atomic_int x; atomic_int y; atomic_int z; diff --git a/tests/correct/litmus/psc-ar/variants/psc-ar0.c b/tests/correct/litmus/psc-ar/variants/psc-ar0.c index 93ad72d..6c4c2ee 100644 --- a/tests/correct/litmus/psc-ar/variants/psc-ar0.c +++ b/tests/correct/litmus/psc-ar/variants/psc-ar0.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../psc-ar.c" diff --git a/tests/correct/litmus/psc-sbhbsb/psc-sbhbsb.c b/tests/correct/litmus/psc-sbhbsb/psc-sbhbsb.c index b355180..1f4742a 100644 --- a/tests/correct/litmus/psc-sbhbsb/psc-sbhbsb.c +++ b/tests/correct/litmus/psc-sbhbsb/psc-sbhbsb.c @@ -13,8 +13,6 @@ * (Print PSC to see the erroneously added edge.) */ -void __VERIFIER_assume(int); - atomic_int x; atomic_int y; diff --git a/tests/correct/litmus/psc-sbhbsb/variants/psc-sbhbsb0.c b/tests/correct/litmus/psc-sbhbsb/variants/psc-sbhbsb0.c index 586c325..a34eed8 100644 --- a/tests/correct/litmus/psc-sbhbsb/variants/psc-sbhbsb0.c +++ b/tests/correct/litmus/psc-sbhbsb/variants/psc-sbhbsb0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../psc-sbhbsb.c" diff --git a/tests/correct/saver/assume-nonclear-path/assume-nonclear-path.c b/tests/correct/saver/assume-nonclear-path/assume-nonclear-path.c index 4e98f11..4f91604 100644 --- a/tests/correct/saver/assume-nonclear-path/assume-nonclear-path.c +++ b/tests/correct/saver/assume-nonclear-path/assume-nonclear-path.c @@ -5,8 +5,6 @@ atomic_int x; atomic_int y; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { for (int i = 1u; i <= N; i++) diff --git a/tests/correct/saver/assume-nonclear-path/variants/assume-nonclear-path0.c b/tests/correct/saver/assume-nonclear-path/variants/assume-nonclear-path0.c index 01050c8..b4fb4be 100644 --- a/tests/correct/saver/assume-nonclear-path/variants/assume-nonclear-path0.c +++ b/tests/correct/saver/assume-nonclear-path/variants/assume-nonclear-path0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../assume-nonclear-path.c" diff --git a/tests/correct/saver/assume-not-postdom/assume-not-postdom.c b/tests/correct/saver/assume-not-postdom/assume-not-postdom.c index 6041446..f6e5f43 100644 --- a/tests/correct/saver/assume-not-postdom/assume-not-postdom.c +++ b/tests/correct/saver/assume-not-postdom/assume-not-postdom.c @@ -4,8 +4,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { for (int i = 1u; i <= N; i++) diff --git a/tests/correct/saver/assume-not-postdom/variants/assume-not-postdom0.c b/tests/correct/saver/assume-not-postdom/variants/assume-not-postdom0.c index 118f6cf..e5ae9e1 100644 --- a/tests/correct/saver/assume-not-postdom/variants/assume-not-postdom0.c +++ b/tests/correct/saver/assume-not-postdom/variants/assume-not-postdom0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../assume-not-postdom.c" diff --git a/tests/correct/saver/assume-postdom/assume-postdom.c b/tests/correct/saver/assume-postdom/assume-postdom.c index f014ee1..595345d 100644 --- a/tests/correct/saver/assume-postdom/assume-postdom.c +++ b/tests/correct/saver/assume-postdom/assume-postdom.c @@ -4,8 +4,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { for (int i = 1u; i <= N; i++) diff --git a/tests/correct/saver/assume-postdom/variants/assume-postdom0.c b/tests/correct/saver/assume-postdom/variants/assume-postdom0.c index 6d3cefd..e63ca59 100644 --- a/tests/correct/saver/assume-postdom/variants/assume-postdom0.c +++ b/tests/correct/saver/assume-postdom/variants/assume-postdom0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../assume-postdom.c" diff --git a/tests/correct/synthetic/SharedPtr/SharedPtr_acqrel.c b/tests/correct/synthetic/SharedPtr/SharedPtr_acqrel.c index 87cec12..3409f4b 100644 --- a/tests/correct/synthetic/SharedPtr/SharedPtr_acqrel.c +++ b/tests/correct/synthetic/SharedPtr/SharedPtr_acqrel.c @@ -1,5 +1,3 @@ -void __VERIFIER_assume(int x); - atomic_int x; atomic_int y; atomic_int z; diff --git a/tests/correct/synthetic/SharedPtr/variants/SharedPtr2.c b/tests/correct/synthetic/SharedPtr/variants/SharedPtr2.c index 86ad4ad..c5a4eb1 100644 --- a/tests/correct/synthetic/SharedPtr/variants/SharedPtr2.c +++ b/tests/correct/synthetic/SharedPtr/variants/SharedPtr2.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../SharedPtr_acqrel.c" diff --git a/tests/correct/synthetic/hwqueue-ra/hwqueue-ra.c b/tests/correct/synthetic/hwqueue-ra/hwqueue-ra.c index f579b85..789a904 100644 --- a/tests/correct/synthetic/hwqueue-ra/hwqueue-ra.c +++ b/tests/correct/synthetic/hwqueue-ra/hwqueue-ra.c @@ -7,8 +7,6 @@ atomic_int back; int r_1, r_2, r_3, r_4; -void __VERIFIER_assume(int); - void enqueue(int a) { int k = atomic_fetch_add_explicit(&back, 1, memory_order_acq_rel); diff --git a/tests/correct/synthetic/hwqueue-ra/variants/hwqueue-ra0.c b/tests/correct/synthetic/hwqueue-ra/variants/hwqueue-ra0.c index 2f2c3dc..6b0e083 100644 --- a/tests/correct/synthetic/hwqueue-ra/variants/hwqueue-ra0.c +++ b/tests/correct/synthetic/hwqueue-ra/variants/hwqueue-ra0.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "../hwqueue-ra.c" diff --git a/tests/correct/synthetic/lamport/lamport_n.c b/tests/correct/synthetic/lamport/lamport_n.c index a7614a9..eacbeff 100644 --- a/tests/correct/synthetic/lamport/lamport_n.c +++ b/tests/correct/synthetic/lamport/lamport_n.c @@ -7,7 +7,6 @@ # define N 3 #endif -void __VERIFIER_assume(intptr_t); #define await(cond) __VERIFIER_assume(cond) atomic_intptr_t b[N+1], x, y; diff --git a/tests/correct/synthetic/lamport/variants/lamport0.c b/tests/correct/synthetic/lamport/variants/lamport0.c index fb7374f..c3db3d0 100644 --- a/tests/correct/synthetic/lamport/variants/lamport0.c +++ b/tests/correct/synthetic/lamport/variants/lamport0.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../lamport_n.c" diff --git a/tests/correct/synthetic/peterson-sc/peterson.c b/tests/correct/synthetic/peterson-sc/peterson.c index 202b5d6..442ea7a 100644 --- a/tests/correct/synthetic/peterson-sc/peterson.c +++ b/tests/correct/synthetic/peterson-sc/peterson.c @@ -4,8 +4,6 @@ atomic_bool flag2; atomic_int turn; /* Atomic integer that holds the ID of the thread whose turn it is */ atomic_bool x; /* Boolean variable to test mutual exclusion */ -void __VERIFIER_assume(int); - void *thread_1(void *arg) { atomic_store_explicit(&flag1, 1, memory_order_seq_cst); diff --git a/tests/correct/synthetic/peterson-sc/variants/peterson0.c b/tests/correct/synthetic/peterson-sc/variants/peterson0.c index 4e48f15..dc87e09 100644 --- a/tests/correct/synthetic/peterson-sc/variants/peterson0.c +++ b/tests/correct/synthetic/peterson-sc/variants/peterson0.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../peterson.c" diff --git a/tests/correct/synthetic/peterson/peterson.c b/tests/correct/synthetic/peterson/peterson.c index 5811cdf..7816958 100644 --- a/tests/correct/synthetic/peterson/peterson.c +++ b/tests/correct/synthetic/peterson/peterson.c @@ -4,8 +4,6 @@ atomic_bool flag2; atomic_int turn; /* Atomic integer that holds the ID of the thread whose turn it is */ atomic_bool x; /* Boolean variable to test mutual exclusion */ -void __VERIFIER_assume(int); - void *thread_1(void *arg) { atomic_store_explicit(&flag1, 1, memory_order_release); diff --git a/tests/correct/synthetic/peterson/variants/peterson0.c b/tests/correct/synthetic/peterson/variants/peterson0.c index 4e48f15..dc87e09 100644 --- a/tests/correct/synthetic/peterson/variants/peterson0.c +++ b/tests/correct/synthetic/peterson/variants/peterson0.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../peterson.c" diff --git a/tests/correct/synthetic/pgsql/pgsql.c b/tests/correct/synthetic/pgsql/pgsql.c index ff88ea1..3c8e92d 100644 --- a/tests/correct/synthetic/pgsql/pgsql.c +++ b/tests/correct/synthetic/pgsql/pgsql.c @@ -17,8 +17,6 @@ atomic_bool latch2 = ATOMIC_VAR_INIT(false); atomic_bool flag1 = ATOMIC_VAR_INIT(true); atomic_bool flag2 = ATOMIC_VAR_INIT(false); -void __VERIFIER_assume(int); - void *thread_1(void *unused) { for (;;) { diff --git a/tests/correct/synthetic/pgsql/variants/pgsql0.c b/tests/correct/synthetic/pgsql/variants/pgsql0.c index 68ee1c3..0ad63d4 100644 --- a/tests/correct/synthetic/pgsql/variants/pgsql0.c +++ b/tests/correct/synthetic/pgsql/variants/pgsql0.c @@ -1,9 +1,9 @@ -#include #include #include +#include #include #include -#include +#include #include "../pgsql.c" diff --git a/tests/correct/synthetic/psc-wb-fixpoint/psc-wb-fixpoint.c b/tests/correct/synthetic/psc-wb-fixpoint/psc-wb-fixpoint.c index 1013590..f61d970 100644 --- a/tests/correct/synthetic/psc-wb-fixpoint/psc-wb-fixpoint.c +++ b/tests/correct/synthetic/psc-wb-fixpoint/psc-wb-fixpoint.c @@ -8,8 +8,6 @@ * between SC writes. */ -void __VERIFIER_assume(int); - atomic_int x; atomic_int y; atomic_int z; diff --git a/tests/correct/synthetic/psc-wb-fixpoint/variants/psc-wb-fixpoint0.c b/tests/correct/synthetic/psc-wb-fixpoint/variants/psc-wb-fixpoint0.c index b438977..76636b6 100644 --- a/tests/correct/synthetic/psc-wb-fixpoint/variants/psc-wb-fixpoint0.c +++ b/tests/correct/synthetic/psc-wb-fixpoint/variants/psc-wb-fixpoint0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../psc-wb-fixpoint.c" diff --git a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0.c b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0.c index 3a4a9d4..3a1be7b 100644 --- a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0.c +++ b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../wb-fp.c" diff --git a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0r.c b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0r.c index bf71c5d..c3a5f2e 100644 --- a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0r.c +++ b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp0r.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../wb-fp.c" diff --git a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp1.c b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp1.c index b34893b..09fff8d 100644 --- a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp1.c +++ b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp1.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../wb-fp.c" diff --git a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp2.c b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp2.c index a7cb598..0639a2c 100644 --- a/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp2.c +++ b/tests/correct/synthetic/psc-wb-fp-sezgin/variants/wb-fp2.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../wb-fp.c" diff --git a/tests/correct/synthetic/psc-wb-fp-sezgin/wb-fp.c b/tests/correct/synthetic/psc-wb-fp-sezgin/wb-fp.c index 22cf921..3638c60 100644 --- a/tests/correct/synthetic/psc-wb-fp-sezgin/wb-fp.c +++ b/tests/correct/synthetic/psc-wb-fp-sezgin/wb-fp.c @@ -3,8 +3,6 @@ atomic_int b; atomic_int c; atomic_int d; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { c = 2; diff --git a/tests/correct/synthetic/psc-wb-why-fxp/psc-wb.c b/tests/correct/synthetic/psc-wb-why-fxp/psc-wb.c index 3ad0e3b..b60609e 100644 --- a/tests/correct/synthetic/psc-wb-why-fxp/psc-wb.c +++ b/tests/correct/synthetic/psc-wb-why-fxp/psc-wb.c @@ -1,5 +1,3 @@ -void __VERIFIER_assume(int); - atomic_int x; atomic_int y; diff --git a/tests/correct/synthetic/psc-wb-why-fxp/variants/psc-wb0.c b/tests/correct/synthetic/psc-wb-why-fxp/variants/psc-wb0.c index d86eeed..0b8bc97 100644 --- a/tests/correct/synthetic/psc-wb-why-fxp/variants/psc-wb0.c +++ b/tests/correct/synthetic/psc-wb-why-fxp/variants/psc-wb0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../psc-wb.c" diff --git a/tests/correct/synthetic/szymanski/szymanski.c b/tests/correct/synthetic/szymanski/szymanski.c index dd49572..0bd48e9 100644 --- a/tests/correct/synthetic/szymanski/szymanski.c +++ b/tests/correct/synthetic/szymanski/szymanski.c @@ -15,8 +15,6 @@ atomic_int x; atomic_int flag1; atomic_int flag2; -void __VERIFIER_assume(int); - void *thread_1(void *unused) { for (int i = 0u; i < N; i++) { diff --git a/tests/correct/synthetic/szymanski/variants/szymanski0.c b/tests/correct/synthetic/szymanski/variants/szymanski0.c index 65faa0a..6bd14f2 100644 --- a/tests/correct/synthetic/szymanski/variants/szymanski0.c +++ b/tests/correct/synthetic/szymanski/variants/szymanski0.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../szymanski.c" diff --git a/tests/correct/synthetic/szymanski/variants/szymanski1.c b/tests/correct/synthetic/szymanski/variants/szymanski1.c index 9f4057f..d20d67d 100644 --- a/tests/correct/synthetic/szymanski/variants/szymanski1.c +++ b/tests/correct/synthetic/szymanski/variants/szymanski1.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "../szymanski.c" diff --git a/tests/correct/synthetic/wb1/variants/wb10.c b/tests/correct/synthetic/wb1/variants/wb10.c index f21b87e..656cefc 100644 --- a/tests/correct/synthetic/wb1/variants/wb10.c +++ b/tests/correct/synthetic/wb1/variants/wb10.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb1.c" diff --git a/tests/correct/synthetic/wb1/variants/wb11.c b/tests/correct/synthetic/wb1/variants/wb11.c index 539c6f7..965a618 100644 --- a/tests/correct/synthetic/wb1/variants/wb11.c +++ b/tests/correct/synthetic/wb1/variants/wb11.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb1.c" diff --git a/tests/correct/synthetic/wb1/wb1.c b/tests/correct/synthetic/wb1/wb1.c index cb0cba1..b14f022 100644 --- a/tests/correct/synthetic/wb1/wb1.c +++ b/tests/correct/synthetic/wb1/wb1.c @@ -1,5 +1,3 @@ -void __VERIFIER_assume(int); - atomic_int x; void *thread1(void *unused) diff --git a/tests/correct/synthetic/wb2/variants/wb20.c b/tests/correct/synthetic/wb2/variants/wb20.c index f06bf3d..67f501c 100644 --- a/tests/correct/synthetic/wb2/variants/wb20.c +++ b/tests/correct/synthetic/wb2/variants/wb20.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb2.c" diff --git a/tests/correct/synthetic/wb2/wb2.c b/tests/correct/synthetic/wb2/wb2.c index 4cf7b74..4c6b48a 100644 --- a/tests/correct/synthetic/wb2/wb2.c +++ b/tests/correct/synthetic/wb2/wb2.c @@ -2,8 +2,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread1(void *arg) { int a = atomic_load_explicit(&x, mo_rlx); diff --git a/tests/correct/synthetic/wb3/variants/wb30.c b/tests/correct/synthetic/wb3/variants/wb30.c index cdee576..f3cac02 100644 --- a/tests/correct/synthetic/wb3/variants/wb30.c +++ b/tests/correct/synthetic/wb3/variants/wb30.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb3.c" diff --git a/tests/correct/synthetic/wb3/wb3.c b/tests/correct/synthetic/wb3/wb3.c index 9799cc9..d2fe32b 100644 --- a/tests/correct/synthetic/wb3/wb3.c +++ b/tests/correct/synthetic/wb3/wb3.c @@ -2,8 +2,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread1(void *arg) { int a = atomic_load_explicit(&x, mo_rlx); diff --git a/tests/correct/synthetic/wb4/variants/wb40.c b/tests/correct/synthetic/wb4/variants/wb40.c index 8a04800..25bb3bd 100644 --- a/tests/correct/synthetic/wb4/variants/wb40.c +++ b/tests/correct/synthetic/wb4/variants/wb40.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb4.c" diff --git a/tests/correct/synthetic/wb4/variants/wb41.c b/tests/correct/synthetic/wb4/variants/wb41.c index 04d79dc..df78118 100644 --- a/tests/correct/synthetic/wb4/variants/wb41.c +++ b/tests/correct/synthetic/wb4/variants/wb41.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb4.c" diff --git a/tests/correct/synthetic/wb4/wb4.c b/tests/correct/synthetic/wb4/wb4.c index 27fbeda..3b190b8 100644 --- a/tests/correct/synthetic/wb4/wb4.c +++ b/tests/correct/synthetic/wb4/wb4.c @@ -2,8 +2,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread1(void *arg) { diff --git a/tests/correct/synthetic/wb5/variants/wb50.c b/tests/correct/synthetic/wb5/variants/wb50.c index 7be3915..ea7c66a 100644 --- a/tests/correct/synthetic/wb5/variants/wb50.c +++ b/tests/correct/synthetic/wb5/variants/wb50.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../wb5.c" diff --git a/tests/correct/synthetic/wb5/wb5.c b/tests/correct/synthetic/wb5/wb5.c index 6df2803..4796741 100644 --- a/tests/correct/synthetic/wb5/wb5.c +++ b/tests/correct/synthetic/wb5/wb5.c @@ -2,8 +2,6 @@ atomic_int x; -void __VERIFIER_assume(int); - void *thread1(void *arg) {