diff --git a/.gitignore b/.gitignore index 0d9cfe2b2ecfb4a609ee6d1c3a813c24a3756795..acdc5c997665e5661db8da87369e862623fe424f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,9 @@ frama_c_journal.ml /distributed _build *.install +*.coverage +_coverage +_bisect # This file is generated (on need) during configure /src/plugins/dune diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e7790a93c5eaf8613644d465fb0e625d541cdb7..2ff2614dc5c9652ab60434fece031bad25a8f044 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -129,36 +129,54 @@ ivette: ################################################################################ ### TESTS +.build_template: &coverage_artifacts + artifacts: + name: coverage-$CI_JOB_NAME + paths: + - _bisect/*.tar.xz + expire_in: 24h + +.build_template: &coverage + variables: + OUT: "_bisect" + <<: *coverage_artifacts + check-ts-api: stage: tests script: - ./nix/build-proxy.sh ts-api + <<: *coverage e-acsl-tests: stage: tests script: - ./nix/build-proxy.sh e-acsl-tests + <<: *coverage e-acsl-dev-tests: stage: tests script: - ./nix/build-proxy.sh e-acsl-dev-tests + <<: *coverage allow_failure: true .build_template: &eva_template stage: tests script: - ./nix/build-proxy.sh eva-$CONFIG-tests + <<: *coverage_artifacts eva-default-tests: variables: CONFIG: "default" + OUT: "_bisect" <<: *eva_template .build_template: &eva_domains parallel: matrix: - - CONFIG: [ + - OUT: "_bisect" + CONFIG: [ "apron", "bitwise", "equality", @@ -171,40 +189,24 @@ eva-default-tests: eva-domains: <<: *eva_template <<: *eva_domains - only: - variables: - - $CI_COMMIT_BRANCH =~ /.*[-_\/.][Ee]va[-_\/.].*/ - - $CI_COMMIT_BRANCH =~ /^[Ee]va[-_\/.].*/ - - $CI_COMMIT_BRANCH =~ /.*[-_\/.][Ee]va$/ - -eva-domains-nightly: - <<: *eva_template - <<: *eva_domains - only: - refs: - - schedules - -eva-domains-release: - <<: *eva_template - <<: *eva_domains - only: - variables: - - $RELEASE == "yes" kernel-tests: stage: tests script: - ./nix/build-proxy.sh kernel-tests + <<: *coverage plugins-tests: stage: tests script: - ./nix/build-proxy.sh plugins-tests + <<: *coverage wp-tests: stage: tests script: - ./nix/build-proxy.sh wp-tests + <<: *coverage external-plugins: stage: tests @@ -259,6 +261,22 @@ build-distrib-tarball: - ./*.tar.gz expire_in: 1 week +# Coverage + +coverage: + stage: distrib + variables: + BISECT_DIR: "_bisect" + script: + - ./nix/shell-checkers.sh "./nix/coverage.sh" + coverage: '/Coverage: \d+\.\d+\%/' + artifacts: + reports: + coverage_report: + coverage_format: cobertura + path: report.xml + expire_in: 1 week + # Check files header header-check: diff --git a/bin/test.sh b/bin/test.sh index ed3665e5275a347b93866410afd5b65b2d988038..5b2da558ae516c3a0aa2f0b98fa967eb0dd75e9e 100755 --- a/bin/test.sh +++ b/bin/test.sh @@ -32,6 +32,7 @@ LOGS= COMMIT= TESTS= SAVE= +COVER= DUNE_ALIAS= DUNE_OPT= @@ -74,7 +75,8 @@ function Usage echo " -u|--update run tests and update oracles (and WP-cache)" echo " -s|--save save dune logs into $DUNE_LOG" echo " -v|--verbose print executed commands" - echo " -j|--jobs <jobs> Run no more than <jobs> commands simultaneously." + echo " -j|--jobs <jobs> run no more than <jobs> commands simultaneously." + echo " --coverage compute test coverage" echo " -h|--help print this help" echo "" echo "VARIABLES" @@ -188,6 +190,11 @@ do CONFIG=$2 shift ;; + "--coverage") + COVER=yes + DUNE_OPT+="--workspace dev/dune-workspace.cover " + shift + ;; "-n"|"--name") ALIAS_NAME=$2 shift @@ -265,6 +272,30 @@ function PullCache fi } +# -------------------------------------------------------------------------- +# --- Coverage +# -------------------------------------------------------------------------- + +function PrepareCoverage +{ + export BISECT_FILE="$(pwd -P)/_bisect/bisect-" + if [ "$COVER" = "yes" ] ; + then + Cmd rm -rf _coverage + Cmd rm -rf _bisect + Cmd mkdir _bisect + fi +} + +function GenerateCoverage +{ + if [ "$COVER" = "yes" ] ; + then + Head "Generating coverage in _coverage ..." + Cmd bisect-ppx-report html --coverage-path=_bisect + fi +} + # -------------------------------------------------------------------------- # --- Test Suite Preparation # -------------------------------------------------------------------------- @@ -446,10 +477,12 @@ function Status SetEnv PullCache +PrepareCoverage PrepareTests Register $TESTS RunAlias ${DUNE_ALIAS} Commits ${COMMITS} Status $DUNE_LOG +GenerateCoverage # -------------------------------------------------------------------------- diff --git a/dev/dune-workspace.cover b/dev/dune-workspace.cover new file mode 100644 index 0000000000000000000000000000000000000000..86349742cd4e9d71bf7ee44ed42b70934fd3cf91 --- /dev/null +++ b/dev/dune-workspace.cover @@ -0,0 +1,26 @@ +(lang dune 3.2) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of Frama-C. ;; +;; ;; +;; Copyright (C) 2007-2023 ;; +;; CEA (Commissariat à l'énergie atomique et aux énergies ;; +;; alternatives) ;; +;; ;; +;; you can redistribute it and/or modify it under the terms of the GNU ;; +;; Lesser General Public License as published by the Free Software ;; +;; Foundation, version 2.1. ;; +;; ;; +;; It 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 Lesser General Public License for more details. ;; +;; ;; +;; See the GNU Lesser General Public License version 2.1 ;; +;; for more details (enclosed in the file licenses/LGPLv2.1). ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(context + (default + (instrument_with bisect_ppx))) diff --git a/nix/combinetura.nix b/nix/combinetura.nix new file mode 100644 index 0000000000000000000000000000000000000000..723530d3a767b3d6cc482bd82ab3b2089f1c7610 --- /dev/null +++ b/nix/combinetura.nix @@ -0,0 +1,31 @@ +{ stdenv +, bisect_ppx +, dune_3 +, findlib +, ocaml +, ppxlib +, xml-light +} : + +stdenv.mkDerivation rec { + pname = "combinetura"; + version = src.version; + + src = (import ./sources.nix {}).combinetura; + + buildInputs = [ + bisect_ppx + dune_3 + findlib + ocaml + xml-light + ]; + + buildPhase = '' + dune build @install + '' ; + + installPhase = '' + dune install --prefix $out --libdir $OCAMLFIND_DESTDIR $pname --docdir $out/share/doc --mandir $out/share/man + '' ; +} diff --git a/nix/coverage.sh b/nix/coverage.sh new file mode 100755 index 0000000000000000000000000000000000000000..f1d8a3ea400516ee284b211301544814cc141ee7 --- /dev/null +++ b/nix/coverage.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2023 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +if [ -z ${BISECT_DIR+x} ]; then + echo "BISECT_DIR variable must indicate the reports directory" + exit 2 +fi + +for i in _bisect/*.tar.xz ; do + tar xfJ "$i" ; +done + +combinetura ./*.xml -o report.xml + +LINE=$(sed -n '2p' report.xml) +RATE=$(echo "$LINE" | sed -e 's/.*line-rate=\"\(.*\)\".*/\1/') + +PERCENT="0.0" +if [ "$RATE" != "-nan" ]; then + # Keep the "/1", bc DOES NOT use scale for anything else than division ... + PERCENT=$(echo "scale=2; (100 * $RATE)/1" | bc -l) +fi + +echo "Coverage: $PERCENT%" diff --git a/nix/default-config-tests.nix b/nix/default-config-tests.nix index 04f0b1bdb3dd8fc6492d23338b6dc90b1d706ba3..a3517e057a72520c946bf507c3612a1244cec3b6 100644 --- a/nix/default-config-tests.nix +++ b/nix/default-config-tests.nix @@ -1,9 +1,13 @@ -{ mk_tests } : +{ mk_tests, frama-c-nocover } : -mk_tests { - tests-name = "default-config-tests"; +let mk_tests_distrib = mk_tests.override { + frama-c = frama-c-nocover ; +}; in +mk_tests_distrib { + cover = false ; + tests-name = "src-distrib-tests" ; tests-command = '' dune exec -- frama-c-ptests -never-disabled tests src/plugins/*/tests dune build -j1 --display short @ptests_config - ''; + '' ; } diff --git a/nix/external-plugin-ci.sh b/nix/external-plugin-ci.sh index e63d692dd76cb206d1174379c38c2645e7927815..fc1bc18392745742b4e9b3ff94e8955d9de7aa75 100755 --- a/nix/external-plugin-ci.sh +++ b/nix/external-plugin-ci.sh @@ -45,6 +45,11 @@ fi # Normalize version for Nix OCAML=${OCAML/./_} +OUTOPT="--no-out-link" +if [ ! -z ${OUT+x} ]; then + OUTOPT="-o $(pwd)/$OUT" +fi + DEFAULT=${DEFAULT:-master} # prints @@ -118,7 +123,7 @@ if [[ -f "./nix/dependencies" ]]; then fi # run the build -nix-build --no-out-link "./nix/pkgs.nix" $OPTS -A ocaml-ng.ocamlPackages_$OCAML."$plugin" +nix-build $OUTOPT "./nix/pkgs.nix" $OPTS -A ocaml-ng.ocamlPackages_$OCAML."$plugin" cd "$fc_dir" diff --git a/nix/frama-c-checkers-shell.nix b/nix/frama-c-checkers-shell.nix index 6bd68e73379d6ec70d3e84673e61e84574d16a86..1456c7a6e92c47759ec74d112db5ef7ec9bee7aa 100644 --- a/nix/frama-c-checkers-shell.nix +++ b/nix/frama-c-checkers-shell.nix @@ -2,6 +2,7 @@ , stdenv , black , clang_10 +, combinetura , frama-c-hdrck , frama-c-lint , git @@ -16,6 +17,7 @@ stdenv.mkDerivation rec { buildInputs = [ black clang_10 + combinetura frama-c-hdrck frama-c-lint git diff --git a/nix/frama-c.nix b/nix/frama-c.nix index 4be82fb950a17b6a28b4a09c0c8834462f96c25d..2aab3256ac2305aff99c5083713502e2d50bd60b 100644 --- a/nix/frama-c.nix +++ b/nix/frama-c.nix @@ -11,6 +11,7 @@ , findlib # Frama-C build , apron +, bisect_ppx , camlzip , camomile , dune_3 @@ -45,7 +46,7 @@ , doxygen , python3 , python3Packages -, yq +, cover ? true , release_mode ? false }: @@ -71,6 +72,7 @@ stdenvNoCC.mkDerivation rec { buildInputs = [ apron + bisect_ppx camlzip camomile dune_3 @@ -105,8 +107,6 @@ stdenvNoCC.mkDerivation rec { dos2unix doxygen python3 - python3Packages.pyaml - yq ]; outputs = [ "out" "build_dir" ]; @@ -121,11 +121,15 @@ stdenvNoCC.mkDerivation rec { enableParallelBuilding = false; dune_opt = if release_mode then "--release" else "" ; - buildPhase = '' - dune build -j2 --display short --error-reporting=twice $release_mode @install - make tools/ptests/ptests.exe - make tools/ptests/wtests.exe - ''; + buildPhase = (if cover then '' + export DUNE_WORKSPACE="dev/dune-workspace.cover" + '' else "") + + '' + dune build -j2 --display short --error-reporting=twice $dune_opt @install + + make tools/ptests/ptests.exe + make tools/ptests/wtests.exe + ''; installFlags = [ "PREFIX=$(out)" diff --git a/nix/mk_tests.nix b/nix/mk_tests.nix index d56dc7155dc3a698acb0d594c8197a887c152761..1754f291e51b51d27fbae62bca47c0477643e129 100644 --- a/nix/mk_tests.nix +++ b/nix/mk_tests.nix @@ -26,6 +26,7 @@ , stdenvNoCC , time , unixtools +, yq , which , wp-cache } : @@ -33,6 +34,7 @@ { tests-name , tests-command , has-wp-proofs ? false +, cover ? true } : stdenvNoCC.mkDerivation { @@ -49,6 +51,7 @@ stdenvNoCC.mkDerivation { perl time unixtools.getopt + yq which ] ++ (if has-wp-proofs then [ alt-ergo ] else []); @@ -68,14 +71,29 @@ stdenvNoCC.mkDerivation { else "" ; preBuild = - if has-wp-proofs + (if has-wp-proofs + then '' + mkdir home + HOME=$(pwd)/home + why3 config detect + export FRAMAC_WP_CACHE=offline + export FRAMAC_WP_CACHEDIR=$wp_cache + '' + else "") + + (if cover + then '' + mkdir -p _bisect + export DUNE_WORKSPACE="dev/dune-workspace.cover" + export BISECT_FILE="$(pwd)/_bisect/bisect-" + '' + else ""); + + postBuild = + if cover then '' - mkdir home - HOME=$(pwd)/home - why3 config detect - export FRAMAC_WP_CACHE=offline - export FRAMAC_WP_CACHEDIR=$wp_cache - '' + bisect-ppx-report cobertura --coverage-path=_bisect coverage-$pname.xml + tar cfJ coverage.tar.xz coverage-$pname.xml + '' else "" ; buildPhase = '' @@ -86,7 +104,13 @@ stdenvNoCC.mkDerivation { ''; # No installation required - installPhase = '' - touch $out - ''; + installPhase = + if cover + then '' + mkdir -p $out + cp -r coverage.tar.xz $out/$pname.tar.xz + '' + else '' + touch $out + ''; } diff --git a/nix/pkgs.nix b/nix/pkgs.nix index 8f08f15e2ed2c3ad9c9f176c69dd830e48dae2a3..69ec600c6a00dace82ffa98d0b4dbd1a110a69ed 100644 --- a/nix/pkgs.nix +++ b/nix/pkgs.nix @@ -4,6 +4,7 @@ let # External Packages alt-ergo = oself.callPackage ./alt-ergo.nix {}; camlp5 = oself.callPackage ./camlp5.nix {}; + combinetura = oself.callPackage ./combinetura.nix {}; headache = oself.callPackage ./headache.nix {}; mlmpfr = oself.callPackage ./mlmpfr.nix {}; why3 = oself.callPackage ./why3.nix {}; @@ -23,11 +24,16 @@ let # Builds frama-c = oself.callPackage ./frama-c.nix {}; + frama-c-no-cover = oself.callPackage ./frama-c.nix { cover = false ; }; frama-c-hdrck = oself.callPackage ./frama-c-hdrck.nix {}; frama-c-lint = oself.callPackage ./frama-c-lint.nix {}; # Tests - default-config-tests = oself.callPackage ./default-config-tests.nix {}; + default-config-tests = oself.callPackage ./default-config-tests.nix { + frama-c-nocover = oself.frama-c.override { + cover = false ; + } ; + }; e-acsl-tests = oself.callPackage ./e-acsl-tests.nix { config = ""; }; e-acsl-dev-tests = oself.callPackage ./e-acsl-tests.nix { config = "dev"; }; eva-default-tests = oself.callPackage ./eva-tests.nix { config = ""; }; @@ -52,7 +58,10 @@ let api-doc = oself.callPackage ./api-doc.nix {}; manuals = oself.callPackage ./manuals.nix {}; src-distrib-tests = oself.callPackage ./src-distrib-tests.nix { - frama-c-release = oself.frama-c.override { release_mode = true ; } ; + frama-c-release = oself.frama-c.override { + release_mode = true ; + cover = false ; + } ; }; }; overlay = self: super: { diff --git a/nix/sources.json b/nix/sources.json index f3366def7224ddf86cc72dba0203100ae2053299..085757d6bd1478f3e88eefa4b4365d295a2e8018 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -41,5 +41,12 @@ "rev": "49c0c5193ef945f1a3dca30b59fa093a7b43437d", "type": "git", "version": "1.6.0" + }, + "combinetura": { + "branch": "master", + "repo": "git@git.frama-c.com:dev/combinetura.git", + "rev": "7e44888e80c34d560da20a220c0ac1ab2126ff0f", + "type": "git", + "version": "0.0" } } diff --git a/nix/src-distrib-tests.nix b/nix/src-distrib-tests.nix index 6655a194c4c6f36aad1c92c81b8da5b2791ca13d..dba013d7aef295da3685b67372136d8dc9d1643d 100644 --- a/nix/src-distrib-tests.nix +++ b/nix/src-distrib-tests.nix @@ -4,9 +4,10 @@ let mk_tests_distrib = mk_tests.override { frama-c = frama-c-release ; }; in mk_tests_distrib { - tests-name = "src-distrib-tests"; + cover = false ; + tests-name = "src-distrib-tests" ; tests-command = '' dune exec -- frama-c-ptests -never-disabled tests src/plugins/*/tests dune build -j1 --display short @ptests_config - ''; + '' ; } diff --git a/nix/ts-api.nix b/nix/ts-api.nix index cda9f980c8d6ef7811f8976bf361654e0af80dc8..5d181a1a77828c79abb308442b8edd916786354d 100644 --- a/nix/ts-api.nix +++ b/nix/ts-api.nix @@ -28,11 +28,16 @@ stdenv.mkDerivation rec { ''; buildPhase = '' + mkdir coverage + export BISECT_FILE="$(pwd)/coverage/bisect-" make -C ivette check-api + bisect-ppx-report cobertura --coverage-path=coverage coverage-$pname.xml + tar cfJ coverage.tar.xz coverage-$pname.xml ''; # No installation required installPhase = '' - touch $out + mkdir -p $out + cp -r coverage.tar.xz $out/$pname.tar.xz ''; } diff --git a/src/dune b/src/dune index 7cd55aa0b825af3628b942e63f2e0b5503c955a6..1df313dfe3b14cf5b89e8942fcd3e73b1a2e9e23 100644 --- a/src/dune +++ b/src/dune @@ -52,6 +52,7 @@ (flags :standard -w -9) (libraries frama-c.init fpath str unix zarith ocamlgraph dynlink bytes yaml.unix yojson menhirLib dune-site dune-site.plugins) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) (preprocess (staged_pps ppx_import ppx_deriving.eq ppx_deriving.ord ppx_deriving_yaml)) ) diff --git a/src/init/boot/dune b/src/init/boot/dune index 99571de6546a5b56beee1f7079c5265df19a5a5c..ad7b0ab70d1895b2764e5ff15d5cb53d75b5908d 100644 --- a/src/init/boot/dune +++ b/src/init/boot/dune @@ -27,6 +27,7 @@ (flags :standard -open Frama_c_kernel) (libraries frama_c_kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) diff --git a/src/init/dune b/src/init/dune index 9187a431dcf969479cd4d5566c7051c1c3160604..a10c21f55224ee9e780edbeabc855b0485c31c70 100644 --- a/src/init/dune +++ b/src/init/dune @@ -27,6 +27,7 @@ (virtual_modules gui_init) (libraries threads) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (include_subdirs no) diff --git a/src/init/impl_cmdline/dune b/src/init/impl_cmdline/dune index 7e8d680abd9dec1ca815acce0930ae1238b48d3b..8467d8184fb4ea1c1b03335fa14fdc66d408cfd4 100644 --- a/src/init/impl_cmdline/dune +++ b/src/init/impl_cmdline/dune @@ -25,4 +25,5 @@ (public_name frama-c.init.cmdline) (implements frama-c.init) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) diff --git a/src/kernel_services/abstract_interp/lattice_bounds.ml b/src/kernel_services/abstract_interp/lattice_bounds.ml index 1e48cad2696860e219610e9ed5df536a8fdd9c78..583d47d1811e751e5e3a1aa9069b11edd55144e8 100644 --- a/src/kernel_services/abstract_interp/lattice_bounds.ml +++ b/src/kernel_services/abstract_interp/lattice_bounds.ml @@ -77,8 +77,8 @@ struct let is_included is_included x y = match x, y with - | `Bottom, _ | _, `Top -> true - | _, `Bottom | `Top, _ -> false + | `Bottom, #or_top_bottom | #or_top_bottom, `Top -> true + | #or_top_bottom, `Bottom | `Top, #or_top_bottom -> false | `Value vx, `Value vy -> is_included vx vy (* Iterator *) @@ -142,7 +142,7 @@ module Bottom = struct let zip x y = match x, y with - | `Bottom, _ | _, `Bottom -> `Bottom + | `Bottom, #t | #t, `Bottom -> `Bottom | `Value x, `Value y -> `Value (x,y) (** Conversion *) @@ -265,7 +265,7 @@ struct let zip x y = match x, y with - | `Top, _ | _, `Top -> `Top + | `Top, #t | #t, `Top -> `Top | `Value x, `Value y -> `Value (x,y) (** Conversion. *) @@ -327,8 +327,8 @@ struct let zip x y = match x, y with - | `Bottom, _ | _, `Bottom -> `Bottom - | `Top, _ | _, `Top -> `Top + | `Bottom, #t | #t, `Bottom -> `Bottom + | `Top, #t | #t, `Top -> `Top | `Value x, `Value y -> `Value (x,y) (** Operators *) diff --git a/src/kernel_services/abstract_interp/value_types.mli b/src/kernel_services/abstract_interp/value_types.mli deleted file mode 100644 index 811e97b24fd8645dacd03b2224d5186e007f8c6a..0000000000000000000000000000000000000000 --- a/src/kernel_services/abstract_interp/value_types.mli +++ /dev/null @@ -1,44 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Declarations that are useful for plugins written on top of the results - of Value. *) - -type 'a callback_result = - | Normal of 'a - | NormalStore of 'a * int - | Reuse of int - -type call_froms = (Function_Froms.froms * Locations.Zone.t) option -(** If not None, the froms of the function, and its sure outputs; - i.e. the dependencies of the result, and the dependencies - of each zone written to. *) - -(** Dependencies for the evaluation of a term or a predicate: for each - program point involved, sets of zones that must be read *) -type logic_dependencies = Locations.Zone.t Cil_datatype.Logic_label.Map.t - -(* -Local Variables: -compile-command: "make -C ../../.." -End: -*) diff --git a/src/kernel_services/plugin_entry_points/db.ml b/src/kernel_services/plugin_entry_points/db.ml index 2cbd4c86ed67b863730b680daac78bcc60029fc0..1da9ccf2e15d1e4cc7265d5ca0a464811ce1d474 100644 --- a/src/kernel_services/plugin_entry_points/db.ml +++ b/src/kernel_services/plugin_entry_points/db.ml @@ -319,20 +319,6 @@ module Value = struct ((i land mask_then) <> 0, (i land mask_else) <> 0) with Not_found -> false, false - module RecursiveCallsFound = - State_builder.Set_ref - (Kernel_function.Set) - (struct - let name = "Db.Value.RecursiveCallsFound" - let dependencies = only_self - end) - - let ignored_recursive_call kf = - RecursiveCallsFound.mem kf - - let recursive_call_occurred kf = - RecursiveCallsFound.add kf - module Called_Functions_By_Callstack = State_builder.Hashtbl(Kernel_function.Hashtbl) (States_by_callstack) @@ -369,54 +355,6 @@ module Value = struct Cvalue.Model.pretty v) *) - module Record_Value_Callbacks = - Hook.Build - (struct - type t = callstack * (state Stmt.Hashtbl.t) Lazy.t - end) - - module Record_Value_Callbacks_New = - Hook.Build - (struct - type t = - callstack * - ((state Stmt.Hashtbl.t) Lazy.t * (state Stmt.Hashtbl.t) Lazy.t) - Value_types.callback_result - end) - - module Record_Value_After_Callbacks = - Hook.Build - (struct - type t = callstack * (state Stmt.Hashtbl.t) Lazy.t - end) - - module Record_Value_Superposition_Callbacks = - Hook.Build - (struct - type t = callstack * (state list Stmt.Hashtbl.t) Lazy.t - end) - - module Call_Value_Callbacks = - Hook.Build - (struct type t = state * callstack end) - - module Call_Type_Value_Callbacks = - Hook.Build(struct - type t = [`Builtin | `Spec - | `Body | `Reuse] - * state * callstack end) - ;; - - - module Compute_Statement_Callbacks = - Hook.Build - (struct type t = stmt * callstack * state list end) - - (* -remove-redundant-alarms feature, applied at the end of an Eva analysis, - fulfilled by the Scope plugin that also depends on Eva. We thus use a - reference here to avoid a cyclic dependency. *) - let rm_asserts = mk_fun "Value.rm_asserts" - let no_results = mk_fun "Value.no_results" let update_callstack_table ~after stmt callstack v = @@ -476,10 +414,6 @@ module Value = struct try Some (Called_Functions_By_Callstack.find kf) with Not_found -> None - let valid_behaviors = mk_fun "Value.get_valid_behaviors" - - let add_formals_to_state = mk_fun "add_formals_to_state" - let get_fundec_from_stmt stmt = let kf = try @@ -536,18 +470,6 @@ module Value = struct Table_By_Callstack.find stmt) with Not_found -> None - let fold_stmt_state_callstack f acc ~after stmt = - assert (is_computed ()); (* this assertion fails during Eva analysis *) - match get_stmt_state_callstack ~after stmt with - | None -> acc - | Some h -> Eva_types.Callstack.Hashtbl.fold (fun _ -> f) h acc - - let fold_state_callstack f acc ~after ki = - assert (is_computed ()); (* this assertion fails during Eva analysis *) - match ki with - | Kglobal -> f (globals_state ()) acc - | Kstmt stmt -> fold_stmt_state_callstack f acc ~after stmt - let is_reachable = Cvalue.Model.is_reachable exception Is_reachable @@ -572,116 +494,8 @@ module Value = struct | Kglobal -> Cvalue.Model.is_reachable (globals_state ()) | Kstmt stmt -> is_reachable_stmt stmt - let is_called = mk_fun "Value.is_called" - let callers = mk_fun "Value.callers" - - let access_location = mk_fun "Value.access_location" - - let find state loc = Cvalue.Model.find state loc - - let access = mk_fun "Value.access" - let access_expr = mk_fun "Value.access_expr" - - let use_spec_instead_of_definition = - mk_fun "Value.use_spec_instead_of_definition" - - let eval_lval = - ref (fun ?with_alarms:_ _ -> mk_labeled_fun "Value.eval_lval") - let eval_expr = - ref (fun ?with_alarms:_ _ -> mk_labeled_fun "Value.eval_expr") - - let eval_expr_with_state = - ref (fun ?with_alarms:_ _ -> mk_labeled_fun "Value.eval_expr_with_state") - - let reduce_by_cond = mk_fun "Value.reduce_by_cond" - - let find_lv_plus = mk_fun "Value.find_lv_plus" - - let pretty_state = Cvalue.Model.pretty - - let pretty = Cvalue.V.pretty - let compute = mk_fun "Value.compute" - let memoize = mk_fun "Value.memoize" - let expr_to_kernel_function = mk_fun "Value.expr_to_kernel_function" - let expr_to_kernel_function_state = - mk_fun "Value.expr_to_kernel_function_state" - - exception Not_a_call - - let call_to_kernel_function call_stmt = match call_stmt.skind with - | Instr (Call (_, fexp, _, _)) -> - let _, called_functions = - !expr_to_kernel_function ?with_alarms:None ~deps:None - (Kstmt call_stmt) fexp - in called_functions - | Instr(Local_init(_, ConsInit(f,_,_),_)) -> - Kernel_function.Hptset.singleton (Globals.Functions.get f) - | _ -> raise Not_a_call - - - let lval_to_loc_with_deps = mk_fun "Value.lval_to_loc_with_deps" - let lval_to_loc_with_deps_state = mk_fun "Value.lval_to_loc_with_deps_state" - let lval_to_loc = mk_fun "Value.lval_to_loc" - let lval_to_offsetmap = mk_fun "Value.lval_to_offsetmap" - let lval_to_offsetmap_state = mk_fun "Value.lval_to_offsetmap_state" - let lval_to_loc_state = mk_fun "Value.lval_to_loc_state" - let lval_to_zone = mk_fun "Value.lval_to_zone" - let lval_to_zone_state = mk_fun "Value.lval_to_zone_state" - let lval_to_zone_with_deps_state = mk_fun "Value.lval_to_zone_with_deps_state" - let lval_to_precise_loc_state = - ref (fun ?with_alarms:_ _ -> mk_labeled_fun "Value.lval_to_precise_loc") - let lval_to_precise_loc_with_deps_state = - mk_fun "Value.lval_to_precise_loc_with_deps_state" - let assigns_inputs_to_zone = mk_fun "Value.assigns_inputs_to_zone" - let assigns_outputs_to_zone = mk_fun "Value.assigns_outputs_to_zone" - let assigns_outputs_to_locations = mk_fun "Value.assigns_outputs_to_locations" - let verify_assigns_froms = mk_fun "Value.verify_assigns_froms" - - module Logic = struct - let eval_predicate = - ref (fun ~pre:_ ~here:_ _ -> - raise - (Extlib.Unregistered_function - "Function 'Value.Logic.eval_predicate' not registered yet")) - - end - - exception Void_Function - - let find_return_loc kf = - try - let ki = Kernel_function.find_return kf in - let lval = match ki with - | { skind = Return (Some ({enode = Lval ((_ , offset) as lval)}), _) } - -> - assert (offset = NoOffset) ; - lval - | { skind = Return (None, _) } -> raise Void_Function - | _ -> assert false - in - !lval_to_loc (Kstmt ki) ?with_alarms:None lval - with Kernel_function.No_Statement -> - (* [JS 2011/05/17] should be better to have another name for this - exception or another one since it is possible to have no return without - returning void (the case when the kf corresponds to a declaration *) - raise Void_Function - - let display = mk_fun "Value.display" - - let emitter = ref Emitter.dummy - -end - -module From = struct - exception Not_lval - - let find_deps_no_transitivity = mk_fun "From.find_deps_no_transitivity" - let find_deps_no_transitivity_state = - mk_fun "From.find_deps_no_transitivity_state" - let find_deps_term_no_transitivity_state = - mk_fun "From.find_deps_term_no_transitivity_state" end (* ************************************************************************* *) diff --git a/src/kernel_services/plugin_entry_points/db.mli b/src/kernel_services/plugin_entry_points/db.mli index 4a82d0b724c34198a6b7dcb7821732989a710ebd..3e820ffff2a188f6965eade123baf0f20a01d628 100644 --- a/src/kernel_services/plugin_entry_points/db.mli +++ b/src/kernel_services/plugin_entry_points/db.mli @@ -109,9 +109,6 @@ module Value : sig type t = Cvalue.V.t (** Internal representation of a value. *) - val emitter: Emitter.t ref - (** Emitter used by Value to emit statuses *) - val proxy: State_builder.Proxy.t val self : State.t @@ -151,23 +148,11 @@ module Value : sig of each reachable and evaluable statement. Filled only if [Value_parameters.ResultsAfter] is set. *) - val ignored_recursive_call: kernel_function -> bool - (** This functions returns true if the value analysis found and ignored - a recursive call to this function during the analysis. *) - val condition_truth_value: stmt -> bool * bool (** Provided [stmt] is an 'if' construct, [fst (condition_truth_value stmt)] (resp. snd) is true if and only if the condition of the 'if' has been evaluated to true (resp. false) at least once during the analysis. *) - (** {3 Parameterization} *) - - val use_spec_instead_of_definition: (kernel_function -> bool) ref - (** To be called by derived analyses to determine if they must use - the body of the function (if available), or only its spec. Used for - value builtins, and option -val-use-spec. *) - - (** {4 Arguments of the main function} *) (** The functions below are related to the arguments that are passed to the @@ -231,65 +216,6 @@ module Value : sig (** [after] is false by default. @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *) - val fold_stmt_state_callstack : - (state -> 'a -> 'a) -> 'a -> after:bool -> stmt -> 'a - - val fold_state_callstack : - (state -> 'a -> 'a) -> 'a -> after:bool -> kinstr -> 'a - - val find : state -> Locations.location -> t - - (** {3 Evaluations} *) - - val eval_lval : - (?with_alarms:CilE.warn_mode -> - Locations.Zone.t option -> - state -> - lval -> - Locations.Zone.t option * t) ref - - val eval_expr : - (?with_alarms:CilE.warn_mode -> state -> exp -> t) ref - - val eval_expr_with_state : - (?with_alarms:CilE.warn_mode -> state -> exp -> state * t) ref - - val reduce_by_cond: - (state -> exp -> bool -> state) ref - - val find_lv_plus : - (Cvalue.Model.t -> Cil_types.exp -> - (Cil_types.lval * Ival.t) list) ref - (** returns the list of all decompositions of [expr] into the sum an lvalue - and an interval. *) - - (** {3 Values and kernel functions} *) - - val expr_to_kernel_function : - (kinstr - -> ?with_alarms:CilE.warn_mode - -> deps:Locations.Zone.t option - -> exp - -> Locations.Zone.t * Kernel_function.Hptset.t) ref - - val expr_to_kernel_function_state : - (state - -> deps:Locations.Zone.t option - -> exp - -> Locations.Zone.t * Kernel_function.Hptset.t) ref - - exception Not_a_call - val call_to_kernel_function : stmt -> Kernel_function.Hptset.t - (** Return the functions that can be called from this call. - @raise Not_a_call if the statement is not a call. *) - - val valid_behaviors: (kernel_function -> state -> funbehavior list) ref - - val add_formals_to_state: (state -> kernel_function -> exp list -> state) ref - (** [add_formals_to_state state kf exps] evaluates [exps] in [state] - and binds them to the formal arguments of [kf] in the resulting - state *) - (** {3 Reachability} *) val is_accessible : kinstr -> bool @@ -298,142 +224,6 @@ module Value : sig val is_reachable_stmt : stmt -> bool - (** {3 About kernel functions} *) - - exception Void_Function - val find_return_loc : kernel_function -> Locations.location - (** Return the location of the returned lvalue of the given function. - @raise Void_Function if the function does not return any value. *) - - val is_called: (kernel_function -> bool) ref - - val callers: (kernel_function -> (kernel_function*stmt list) list) ref - (** @return the list of callers with their call sites. Each function is - present only once in the list. *) - - (** {3 State before a kinstr} *) - - val access : (kinstr -> lval -> t) ref - val access_expr : (kinstr -> exp -> t) ref - val access_location : (kinstr -> Locations.location -> t) ref - - - (** {3 Locations of left values} *) - - val lval_to_loc : - (kinstr -> ?with_alarms:CilE.warn_mode -> lval -> Locations.location) ref - - val lval_to_loc_with_deps : - (kinstr - -> ?with_alarms:CilE.warn_mode - -> deps:Locations.Zone.t - -> lval - -> Locations.Zone.t * Locations.location) ref - - val lval_to_loc_with_deps_state : - (state - -> deps:Locations.Zone.t - -> lval - -> Locations.Zone.t * Locations.location) ref - - val lval_to_loc_state : - (state -> lval -> Locations.location) ref - - val lval_to_offsetmap : - ( kinstr -> ?with_alarms:CilE.warn_mode -> lval -> - Cvalue.V_Offsetmap.t option) ref - - val lval_to_offsetmap_state : - (state -> lval -> Cvalue.V_Offsetmap.t option) ref - (** @since Carbon-20110201 *) - - val lval_to_zone : - (kinstr -> ?with_alarms:CilE.warn_mode -> lval -> Locations.Zone.t) ref - - val lval_to_zone_state : - (state -> lval -> Locations.Zone.t) ref - (** Does not emit alarms. *) - - val lval_to_zone_with_deps_state: - (state -> for_writing:bool -> deps:Locations.Zone.t option -> lval -> - Locations.Zone.t * Locations.Zone.t * bool) ref - (** [lval_to_zone_with_deps_state state ~for_writing ~deps lv] computes - [res_deps, zone_lv, exact], where [res_deps] are the memory zones needed - to evaluate [lv] in [state] joined with [deps]. [zone_lv] contains the - valid memory zones that correspond to the location that [lv] evaluates - to in [state]. If [for_writing] is true, [zone_lv] is restricted to - memory zones that are writable. [exact] indicates that [lv] evaluates - to a valid location of cardinal at most one. *) - - val lval_to_precise_loc_state: - (?with_alarms:CilE.warn_mode -> state -> lval -> - state * Precise_locs.precise_location * typ) ref - - val lval_to_precise_loc_with_deps_state: - (state -> deps:Locations.Zone.t option -> lval -> - Locations.Zone.t * Precise_locs.precise_location) ref - - - (** Evaluation of the [\from] clause of an [assigns] clause.*) - val assigns_inputs_to_zone : - (state -> assigns -> Locations.Zone.t) ref - - (** Evaluation of the left part of [assigns] clause (without [\from]).*) - val assigns_outputs_to_zone : - (state -> result:varinfo option -> assigns -> Locations.Zone.t) ref - - (** Evaluation of the left part of [assigns] clause (without [\from]). Each - assigns term results in one location. *) - val assigns_outputs_to_locations : - (state -> result:varinfo option -> assigns -> Locations.location list) ref - - (** For internal use only. Evaluate the [assigns] clause of the - given function in the given prestate, compare it with the - computed froms, return warning and set statuses. *) - val verify_assigns_froms : - (Kernel_function.t -> pre:state -> Function_Froms.t -> unit) ref - - - (** {3 Evaluation of logic terms and predicates} *) - module Logic : sig - (** The APIs of this module are not stabilized yet, and are subject - to change between Frama-C versions. *) - - val eval_predicate: - (pre:state -> here:state -> predicate -> - Property_status.emitted_status) ref - (** Evaluate the given predicate in the given states for the Pre - and Here ACSL labels. - @since Neon-20140301 *) - end - - - (** {3 Callbacks} *) - - (** Actions to perform at end of each function analysis. Not compatible with - option [-memexec-all] *) - - module Record_Value_Callbacks: - Hook.Iter_hook - with type param = callstack * (state Stmt.Hashtbl.t) Lazy.t - - module Record_Value_Superposition_Callbacks: - Hook.Iter_hook - with type param = callstack * (state list Stmt.Hashtbl.t) Lazy.t - - module Record_Value_After_Callbacks: - Hook.Iter_hook - with type param = callstack * (state Stmt.Hashtbl.t) Lazy.t - - (**/**) - (* Temporary API, do not use *) - module Record_Value_Callbacks_New: Hook.Iter_hook - with type param = - callstack * - ((state Stmt.Hashtbl.t) Lazy.t (* before states *) * - (state Stmt.Hashtbl.t) Lazy.t) (* after states *) - Value_types.callback_result - (**/**) val no_results: (fundec -> bool) ref (** Returns [true] if the user has requested that no results should @@ -441,38 +231,6 @@ module Value : sig on [Record_Value_Callbacks] and [Record_Value_Callbacks_New] should not force their lazy argument *) - (** Actions to perform at each treatment of a "call" - statement. [state] is the state before the call. - @deprecated Use Call_Type_Value_Callbacks instead. *) - module Call_Value_Callbacks: - Hook.Iter_hook with type param = state * callstack - - (** Actions to perform at each treatment of a "call" - statement. [state] is the state before the call. - @since Aluminium-20160501 *) - module Call_Type_Value_Callbacks: - Hook.Iter_hook with type param = - [`Builtin | `Spec | `Body | `Reuse] - * state * callstack - - - (** Actions to perform whenever a statement is handled. *) - module Compute_Statement_Callbacks: - Hook.Iter_hook with type param = stmt * callstack * state list - - (* -remove-redundant-alarms feature, applied at the end of an Eva analysis, - fulfilled by the Scope plugin that also depends on Eva. We thus use a - reference here to avoid a cyclic dependency. *) - val rm_asserts: (unit -> unit) ref - - - (** {3 Pretty printing} *) - - val pretty : Format.formatter -> t -> unit - val pretty_state : Format.formatter -> state -> unit - - - val display : (Format.formatter -> kernel_function -> unit) ref (**/**) (** {3 Internal use only} *) @@ -481,8 +239,6 @@ module Value : sig (** To be used during the value analysis itself (instead of {!get_state}). [after] is false by default. *) - val recursive_call_occurred: kernel_function -> unit - val merge_conditions: int Cil_datatype.Stmt.Hashtbl.t -> unit val mask_then: int val mask_else: int @@ -492,12 +248,6 @@ module Value : sig val update_callstack_table: after:bool -> stmt -> callstack -> state -> unit (* Merge a new state in the table indexed by callstacks. *) - - val memoize : (kernel_function -> unit) ref - (* val compute_call : - (kernel_function -> call_kinstr:kinstr -> state -> (exp*t) list - -> Cvalue.V_Offsetmap.t option (** returned value of [kernel_function] *) * state) ref - *) val merge_initial_state : callstack -> kernel_function -> state -> unit (** Store an additional possible initial state for the given callstack as well as its values for actuals. *) @@ -508,30 +258,6 @@ end "Db.Value is deprecated and will be removed in a future version \ of Frama-C. Please use the Eva.mli public API instead."] -(** Functional dependencies between function inputs and function outputs. - @see <../from/index.html> internal documentation. *) -module From : sig - - (** exception raised by [find_deps_no_transitivity_*] if the given expression - is not an lvalue. - @since Aluminium-20160501 - *) - exception Not_lval - - val find_deps_no_transitivity : (stmt -> exp -> Locations.Zone.t) ref - - val find_deps_no_transitivity_state : - (Cvalue.Model.t -> exp -> Locations.Zone.t) ref - - (** @raise Not_lval if the given expression is not a C lvalue. *) - val find_deps_term_no_transitivity_state : - (Cvalue.Model.t -> term -> Value_types.logic_dependencies) ref - -end -[@@alert db_deprecated - "Db.From is deprecated and will be removed in a future version \ - of Frama-C. Please use the From module or the Eva API instead."] - (* ************************************************************************* *) (** {2 Plugins} *) (* ************************************************************************* *) diff --git a/src/plugins/alias/dune b/src/plugins/alias/dune index 63d49ab5cc95c628ad7d0cf25789504a89d9b823..480ffb1277133e4926f5ed26129715b08d444246 100644 --- a/src/plugins/alias/dune +++ b/src/plugins/alias/dune @@ -36,6 +36,7 @@ (flags -open Frama_c_kernel :standard) (libraries frama-c.kernel ocamlgraph unionFind) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) ( plugin diff --git a/src/plugins/aorai/dune b/src/plugins/aorai/dune index 8c8a1eba3314648a79347cf1b4bab0fa271673dc..23a75aa916fa376e4efa41337af9660a2f21ed6c 100644 --- a/src/plugins/aorai/dune +++ b/src/plugins/aorai/dune @@ -45,6 +45,7 @@ ) ) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (ocamllex yalexer) diff --git a/src/plugins/api-generator/dune b/src/plugins/api-generator/dune index 3d7931417a1a98e8aef73b922cac820a6b0a1e51..204f73e2bd785ba731bef1db9669eb1cd52f34a6 100644 --- a/src/plugins/api-generator/dune +++ b/src/plugins/api-generator/dune @@ -26,6 +26,7 @@ (public_name frama-c-api-generator.core) (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-server.core) -) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx))) (plugin (optional) (name api_generator) (libraries frama-c-api-generator.core) (site (frama-c plugins))) diff --git a/src/plugins/callgraph/dune b/src/plugins/callgraph/dune index b1ad818441d91a05e9a224d85cdaf1c7a1eafc3d..64ffc157d4cd564cc6a03a431dc2bb2bebec8694 100644 --- a/src/plugins/callgraph/dune +++ b/src/plugins/callgraph/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name callgraph) (libraries frama-c-callgraph.core) (site (frama-c plugins))) diff --git a/src/plugins/constant_propagation/dune b/src/plugins/constant_propagation/dune index 048101730ad1607edc551bee7a59fefadc666fdb..408db9a7f9c8ab6a5cb2a4ed63f7de52661cc153 100644 --- a/src/plugins/constant_propagation/dune +++ b/src/plugins/constant_propagation/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name constant_propagation) (libraries frama-c-constant_propagation.core) (site (frama-c plugins))) diff --git a/src/plugins/dive/dune b/src/plugins/dive/dune index 85e0415bdd0ea3cd1484f0b6c5c04e6743c857a4..a2c5d6b6e7e3fbb850f98f329704608a7b5db953 100644 --- a/src/plugins/dive/dune +++ b/src/plugins/dive/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-studia.core frama-c-server.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name dive) (libraries frama-c-dive.core) (site (frama-c plugins))) diff --git a/src/plugins/e-acsl/src/dune b/src/plugins/e-acsl/src/dune index ee4a92ec6045a32ec7cc70b1b63644a466c93e38..a46349bec0d4c72f5625e42bd2361fc015b8edb7 100644 --- a/src/plugins/e-acsl/src/dune +++ b/src/plugins/e-acsl/src/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-rtegen.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name e-acsl) (libraries frama-c-e-acsl.core) (site (frama-c plugins))) diff --git a/src/plugins/eva/Eva.mli b/src/plugins/eva/Eva.mli index 3357d50d8349a3d3e2e90fe704eb5394b2b9109d..9d6baa29c8440b1deaab66ab6fdfbdbc366c91cb 100644 --- a/src/plugins/eva/Eva.mli +++ b/src/plugins/eva/Eva.mli @@ -685,6 +685,11 @@ module Cvalue_callbacks: sig type state = Cvalue.Model.t + (** If not None, the froms of the function, and its sure outputs; + i.e. the dependencies of the result, and the dependencies + of each zone written to. *) + type call_froms = (Function_Froms.froms * Locations.Zone.t) option + type analysis_kind = [ `Builtin (** A cvalue builtin is used to interpret the function. *) | `Spec (** The specification is used to interpret the function. *) @@ -708,7 +713,7 @@ module Cvalue_callbacks: sig (** Results of a function call. *) type call_results = - [ `Builtin of state list * Value_types.call_froms + [ `Builtin of state list * call_froms (** List of cvalue states at the end of the builtin. *) | `Spec of state list (** List of cvalue states at the end of the call. *) diff --git a/src/plugins/eva/domains/cvalue/builtins_misc.ml b/src/plugins/eva/domains/cvalue/builtins_misc.ml index 93fbcf970dc1d94407aa23aed067188751b4f5b3..47d8da9c980db7c8e0dad4beb6625dd7aef98d90 100644 --- a/src/plugins/eva/domains/cvalue/builtins_misc.ml +++ b/src/plugins/eva/domains/cvalue/builtins_misc.ml @@ -22,6 +22,7 @@ open Eva_utils +open Lattice_bounds.Bottom.Operators let frama_C_assert state actuals = let do_bottom () = @@ -35,10 +36,14 @@ let frama_C_assert state actuals = then do_bottom () else if Cvalue.V.contains_zero arg then begin - let state = !Db.Value.reduce_by_cond state arg_exp true in - if Cvalue.Model.is_reachable state - then (warning_once_current "Frama_C_assert: unknown"; state) - else do_bottom () + let state = + let* valuation = fst (Cvalue_queries.reduce state arg_exp true) in + let valuation = Cvalue_queries.to_domain_valuation valuation in + Cvalue_transfer.update valuation state + in + match state with + | `Value state -> warning_once_current "Frama_C_assert: unknown"; state + | `Bottom -> do_bottom () end else begin warning_once_current "Frama_C_assert: true"; diff --git a/src/plugins/eva/domains/cvalue/builtins_split.ml b/src/plugins/eva/domains/cvalue/builtins_split.ml index 5d6721b188a2ca2c2efc6d93ea2834e83db29bb5..a6a2cf2812a911993cd1ed76bfefdec413ca2933 100644 --- a/src/plugins/eva/domains/cvalue/builtins_split.ml +++ b/src/plugins/eva/domains/cvalue/builtins_split.ml @@ -74,7 +74,7 @@ let warning warn s = [max_card] elements. *) let split_v ~warn lv state max_card = if Cil.isArithmeticOrPointerType (Cil.typeOfLval lv) then - let loc = !Db.Value.lval_to_loc_state state lv in + let loc = Cvalue_queries.lval_to_loc state lv in if Locations.Location_Bits.cardinal_zero_or_one loc.Locations.loc then let v_indet = Cvalue.Model.find_indeterminate state loc in let v = Cvalue.V_Or_Uninitialized.get_v v_indet in diff --git a/src/plugins/eva/domains/cvalue/builtins_watchpoint.ml b/src/plugins/eva/domains/cvalue/builtins_watchpoint.ml index 39c576d07b60206c8b24bbb7bc700503bc983aa2..695278f28d6f4ae42c1d87c4c3887acdce294c40 100644 --- a/src/plugins/eva/domains/cvalue/builtins_watchpoint.ml +++ b/src/plugins/eva/domains/cvalue/builtins_watchpoint.ml @@ -96,7 +96,7 @@ let () = Builtins.register_builtin "Frama_C_watch_cardinal" Cacheable (add_watch make_watch_cardinal) -let watch_hook (stmt, _callstack, states) = +let watch_hook _callstack stmt states = let treat ({name_lv = name; loc=loc; v=wa; remaining_count=current; stmts=set} as w) = List.iter (fun state -> @@ -132,7 +132,7 @@ let watch_hook (stmt, _callstack, states) = in List.iter treat !watch_table -let () = Db.Value.Compute_Statement_Callbacks.extend_once watch_hook +let () = Cvalue_callbacks.register_statement_hook watch_hook (* Local Variables: diff --git a/src/plugins/eva/domains/cvalue/cvalue_domain.ml b/src/plugins/eva/domains/cvalue/cvalue_domain.ml index 7822ad59369304d3781cdaa189f1c2abfb0fac4a..c6f8db8b6f69c634ccfd265263e9bd025c290884 100644 --- a/src/plugins/eva/domains/cvalue/cvalue_domain.ml +++ b/src/plugins/eva/domains/cvalue/cvalue_domain.ml @@ -24,142 +24,14 @@ open Eval let dkey_card = Self.register_category "cardinal" -module Model = struct +module State = struct - include Cvalue.Model + type state = Cvalue.Model.t * Locals_scoping.clobbered_set type value = Main_values.CVal.t type location = Main_locations.PLoc.location - (* The origin is the value stored in the state for a lvalue, when this value - has a type incompatible with the type of the lvalue. This may happen on - union with fields of different types, or on code pattern such as - int x = v; float f = *(float* )&x - In this case, the value stored in the state and the value computed for the - lvalue can be incomparable. The origin is then used to store the value from - the state, to later choose which value to keep. This is done by the update - function in cvalue_transfer. *) - type origin = value - - let extract_expr _state _expr = `Value (Cvalue.V.top, None), Alarmset.all - - let indeterminate_alarms lval v = - let open Cvalue.V_Or_Uninitialized in - let status = - if Cvalue.V.is_bottom (get_v v) then Alarmset.False else Alarmset.Unknown - in - match v with - | C_uninit_noesc _ -> Alarmset.singleton ~status (Alarms.Uninitialized lval) - | C_init_esc _ -> Alarmset.singleton ~status (Alarms.Dangling lval) - | C_uninit_esc _ -> - (* Unknown alarms: [v] can be either dangling or uninit *) - Alarmset.(set (Alarms.Dangling lval) Unknown - (set (Alarms.Uninitialized lval) Unknown none)) - | C_init_noesc _ -> Alarmset.none - - - let eval_one_loc state lval typ = - let eval_one_loc single_loc = - let v = Cvalue.Model.find_indeterminate state single_loc in - Cvalue.V_Or_Uninitialized.get_v v, indeterminate_alarms lval v - in - (* We have no good neutral element for "no alarm emitted yet", so we use - [None] instead. *) - let join_alarms acc alarms = - match acc with - | None -> Some alarms - | Some acc -> Some (Alarmset.union alarms acc) - in - fun loc (acc_result, acc_alarms) -> - let result, alarms = eval_one_loc loc in - let result = Cvalue_forward.make_volatile ~typ:typ result in - Cvalue.V.join result acc_result, join_alarms acc_alarms alarms - - (* The zero singleton is shared between float and integer representations in - ival, and is thus untyped. *) - let is_float v = - Cvalue.V.(is_included v top_float) && Cvalue.V.contains_non_zero v - - let extract_scalar_lval state lval typ loc = - let process_one_loc = eval_one_loc state lval typ in - let acc = Cvalue.V.bottom, None in - let value, alarms = Precise_locs.fold process_one_loc loc acc in - let alarms = match alarms with None -> Alarmset.none | Some a -> a in - (* The origin is set to false when the value stored in the memory has not - the same type as the read lvalue. In this case, we don't update the state - with the new value stemming from the evaluation, even if it has been - reduced, in order to not propagate incompatible type. *) - let incompatible_type = is_float value <> Cil.isFloatingType typ in - let origin = if incompatible_type then Some value else None in - let value = Cvalue_forward.reinterpret typ value in - if Cvalue.V.is_bottom value - then `Bottom, alarms - else `Value (value, origin), alarms - - (* Imprecise version for aggregate types that cvalues are unable to precisely - represent. The initialization alarms must remain sound, though. *) - let extract_aggregate_lval state lval _typ ploc = - let loc = Precise_locs.imprecise_location ploc in - match loc.Locations.size with - | Int_Base.Top -> `Value (Cvalue.V.top, None), Alarmset.all - | Int_Base.Value size -> - let offsm = Cvalue.Model.copy_offsetmap loc.Locations.loc size state in - match offsm with - | `Bottom -> `Bottom, Alarmset.none - | `Value offsm -> - let value = Cvalue.V_Offsetmap.find_imprecise_everywhere offsm in - let alarms = indeterminate_alarms lval value in - let v = Cvalue.V_Or_Uninitialized.get_v value in - let v = if Cvalue.V.is_bottom v then `Bottom else `Value (v, None) in - v, alarms - - let extract_lval state lval typ loc = - if Cil.isArithmeticOrPointerType typ - then extract_scalar_lval state lval typ loc - else extract_aggregate_lval state lval typ loc - - let backward_location state _lval typ precise_loc value = - let size = Precise_locs.loc_size precise_loc in - let upto = succ (Int_set.get_small_cardinal()) in - let loc = Precise_locs.imprecise_location precise_loc in - let eval_one_loc single_loc = - let v = Cvalue.Model.find state single_loc in - let v = Cvalue_forward.make_volatile ~typ v in - Cvalue_forward.reinterpret typ v - in - let process_ival base ival (acc_loc, acc_val as acc) = - let loc_bits = Locations.Location_Bits.inject base ival in - let single_loc = Locations.make_loc loc_bits size in - let v = eval_one_loc single_loc in - if Cvalue.V.intersects v value - then Locations.Location_Bits.join loc_bits acc_loc, Cvalue.V.join v acc_val - else acc - in - let fold_ival base ival acc = - if Ival.cardinal_is_less_than ival upto - then Ival.fold_enum (process_ival base) ival acc - else process_ival base ival acc - in - let fold_location loc acc = - try - let loc = loc.Locations.loc in - Locations.Location_Bits.fold_i fold_ival loc acc - with - Abstract_interp.Error_Top -> loc.Locations.loc, value - in - let acc = Locations.Location_Bits.bottom, Cvalue.V.bottom in - let loc_bits, value = fold_location loc acc in - if Locations.Location_Bits.is_bottom loc_bits - then `Bottom - else - let loc = Precise_locs.inject_location_bits loc_bits in - `Value (Precise_locs.make_precise_loc loc ~size, value) - -end - - -module State = struct - - type state = Model.t * Locals_scoping.clobbered_set + let value_dependencies = Main_values.cval + let location_dependencies = Main_locations.ploc let log_category = Self.dkey_cvalue_domain @@ -167,15 +39,16 @@ module State = struct struct include Datatype.Serializable_undefined type t = state - let name = Model.name ^ "+clobbered_set" - let reprs = List.map (fun s -> s, Locals_scoping.bottom ()) Model.reprs + let name = Cvalue.Model.name ^ "+clobbered_set" + let reprs = + List.map (fun s -> s, Locals_scoping.bottom ()) Cvalue.Model.reprs let structural_descr = - Structural_descr.( - t_tuple [| Model.packed_descr; pack Locals_scoping.structural_descr |]) - let pretty fmt (s, _) = Model.pretty fmt s - let equal (a, _) (b, _) = Model.equal a b - let compare (a, _) (b, _) = Model.compare a b - let hash (s, _) = Model.hash s + Structural_descr.t_tuple + [| Cvalue.Model.packed_descr; Locals_scoping.packed_descr |] + let pretty fmt (s, _) = Cvalue.Model.pretty fmt s + let equal (a, _) (b, _) = Cvalue.Model.equal a b + let compare (a, _) (b, _) = Cvalue.Model.compare a b + let hash (s, _) = Cvalue.Model.hash s let rehash = Datatype.identity let copy = Datatype.undefined let mem_project = Datatype.never_any_project @@ -184,33 +57,31 @@ module State = struct let name = "cvalue" let key = Structure.Key_Domain.create_key name - type value = Model.value - type location = Model.location - - let value_dependencies = Main_values.cval - let location_dependencies = Main_locations.ploc - - let top = Model.top, Locals_scoping.bottom () - let is_included (a, _) (b, _) = Model.is_included a b - let join (a, clob) (b, _) = Model.join a b, clob + let top = Cvalue.Model.top, Locals_scoping.bottom () + let is_included (a, _) (b, _) = Cvalue.Model.is_included a b + let join (a, clob) (b, _) = Cvalue.Model.join a b, clob let widen kf stmt (a, clob) (b, _) = let hint = Widen.getWidenHints kf stmt in - Model.widen hint a b, clob + Cvalue.Model.widen hint a b, clob let narrow (a, clob) (b, _) = - let s = Model.narrow a b in - if Model.(equal bottom s) then `Bottom else `Value (s, clob) + let s = Cvalue.Model.narrow a b in + if Cvalue.Model.(equal bottom s) then `Bottom else `Value (s, clob) + + type origin = Cvalue_queries.origin - type origin = Model.origin + let extract_expr ~oracle context (state, _) expr = + Cvalue_queries.extract_expr ~oracle context state expr + + let extract_lval ~oracle context (state, _) lval typ loc = + Cvalue_queries.extract_lval ~oracle context state lval typ loc - let extract_expr ~oracle:_ _context (s, _) expr = - Model.extract_expr s expr - let extract_lval ~oracle:_ _context (s, _) lval typ loc = - Model.extract_lval s lval typ loc let backward_location (state, _) lval typ precise_loc value = - Model.backward_location state lval typ precise_loc value - let reduce_further _ _ _ = [] + Cvalue_queries.backward_location state lval typ precise_loc value + + let reduce_further (state, _) expr value = + Cvalue_queries.reduce_further state expr value (* ------------------------------------------------------------------------ *) (* Transfer Functions *) @@ -241,11 +112,11 @@ module State = struct let start_recursive_call stmt call recursion (state, clob) = let direct = is_direct_recursion stmt call in - let state = Model.remove_variables recursion.withdrawal state in + let state = Cvalue.Model.remove_variables recursion.withdrawal state in let substitution = recursion.base_substitution in let clob = if direct then clob else Locals_scoping.top () in let state = Locals_scoping.substitute substitution clob state in - Model.replace_base substitution state + Cvalue.Model.replace_base substitution state let start_call stmt call recursion valuation (state, clob) = (* Uses the [valuation] to update the [state] before the substitution @@ -263,7 +134,7 @@ module State = struct let direct = is_direct_recursion stmt call in let pre, clob = pre in let substitution = recursion.base_substitution in - let state = Model.replace_base substitution state in + let state = Cvalue.Model.replace_base substitution state in let clob = if direct then clob else Locals_scoping.top () in let state = Locals_scoping.substitute substitution clob state in let inter = Cvalue.Model.filter_by_shape recursion.base_withdrawal pre in @@ -365,7 +236,7 @@ module State = struct else Cvalue.V_Or_Uninitialized.C_uninit_noesc value in let loc = Precise_locs.imprecise_location loc in - Model.add_indeterminate_binding ~exact:true state loc cvalue, clob + Cvalue.Model.add_indeterminate_binding ~exact:true state loc cvalue, clob let empty () = let open Cvalue in @@ -399,7 +270,7 @@ module State = struct | Abstract_domain.Result kf -> let value = Library_functions.returned_value kf in let loc = Locations.loc_of_varinfo varinfo in - Model.add_binding ~exact:true state loc value, clob + Cvalue.Model.add_binding ~exact:true state loc value, clob (* ------------------------------------------------------------------------ *) (* Misc *) @@ -416,13 +287,13 @@ module State = struct else Bottom.non_bottom (Cvalue.Default_offsetmap.default_offsetmap b) in - Model.add_base b offsm state + Cvalue.Model.add_base b offsm state let bind_global state varinfo = let base = Base.of_varinfo varinfo in let loc = Locations.loc_of_base base in let value = Cvalue.V_Or_Uninitialized.uninitialized in - Model.add_indeterminate_binding ~exact:true state loc value + Cvalue.Model.add_indeterminate_binding ~exact:true state loc value let enter_scope kind vars (state, clob) = let bind = @@ -433,7 +304,7 @@ module State = struct List.fold_left bind state vars, clob let leave_scope kf vars (state, clob) = - let state = Model.remove_variables vars state in + let state = Cvalue.Model.remove_variables vars state in try let fdec = Kernel_function.get_definition kf in Locals_scoping.make_escaping_fundec fdec clob vars state, clob @@ -584,8 +455,6 @@ module State = struct then Parameters.ForceValues.output display_results end -let () = Db.Value.display := (fun fmt kf -> State.display ~fmt kf) - let registered = let name = "cvalue" @@ -597,16 +466,16 @@ let registered = type prefix = Hptmap.prefix module Subpart = struct - type t = Model.subtree - let hash = Model.hash_subtree - let equal = Model.equal_subtree + type t = Cvalue.Model.subtree + let hash = Cvalue.Model.hash_subtree + let equal = Cvalue.Model.equal_subtree end let distinct_subpart (a, _) (b, _) = - if Model.equal a b then None + if Cvalue.Model.equal a b then None else - try Model.comp_prefixes a b; None - with Model.Found_prefix (p, s1, s2) -> Some (p, s1, s2) -let find_subpart (s, _) prefix = Model.find_prefix s prefix + try Cvalue.Model.comp_prefixes a b; None + with Cvalue.Model.Found_prefix (p, s1, s2) -> Some (p, s1, s2) +let find_subpart (s, _) prefix = Cvalue.Model.find_prefix s prefix module Getters (Dom : Abstract.Domain.External) = struct diff --git a/src/plugins/eva/domains/cvalue/cvalue_queries.ml b/src/plugins/eva/domains/cvalue/cvalue_queries.ml new file mode 100644 index 0000000000000000000000000000000000000000..ae31230b0e8ede332ce8a485e99431acb7c51d83 --- /dev/null +++ b/src/plugins/eva/domains/cvalue/cvalue_queries.ml @@ -0,0 +1,184 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Queries = struct + + type state = Cvalue.Model.t + type value = Main_values.CVal.t + type location = Main_locations.PLoc.location + + (* The origin is the value stored in the state for a lvalue, when this value + has a type incompatible with the type of the lvalue. This may happen on + union with fields of different types, or on code pattern such as + int x = v; float f = *(float* )&x + In this case, the value stored in the state and the value computed for the + lvalue can be incomparable. The origin is then used to store the value from + the state, to later choose which value to keep. This is done by the update + function in cvalue_transfer. *) + type origin = value + + let extract_expr ~oracle:_ _context _state _expr = + `Value (Cvalue.V.top, None), Alarmset.all + + let indeterminate_alarms lval v = + let open Cvalue.V_Or_Uninitialized in + let status = + if Cvalue.V.is_bottom (get_v v) then Alarmset.False else Alarmset.Unknown + in + match v with + | C_uninit_noesc _ -> Alarmset.singleton ~status (Alarms.Uninitialized lval) + | C_init_esc _ -> Alarmset.singleton ~status (Alarms.Dangling lval) + | C_uninit_esc _ -> + (* Unknown alarms: [v] can be either dangling or uninit *) + Alarmset.(set (Alarms.Dangling lval) Unknown + (set (Alarms.Uninitialized lval) Unknown none)) + | C_init_noesc _ -> Alarmset.none + + + let eval_one_loc state lval typ = + let eval_one_loc single_loc = + let v = Cvalue.Model.find_indeterminate state single_loc in + Cvalue.V_Or_Uninitialized.get_v v, indeterminate_alarms lval v + in + (* We have no good neutral element for "no alarm emitted yet", so we use + [None] instead. *) + let join_alarms acc alarms = + match acc with + | None -> Some alarms + | Some acc -> Some (Alarmset.union alarms acc) + in + fun loc (acc_result, acc_alarms) -> + let result, alarms = eval_one_loc loc in + let result = Cvalue_forward.make_volatile ~typ:typ result in + Cvalue.V.join result acc_result, join_alarms acc_alarms alarms + + (* The zero singleton is shared between float and integer representations in + ival, and is thus untyped. *) + let is_float v = + Cvalue.V.(is_included v top_float) && Cvalue.V.contains_non_zero v + + let extract_scalar_lval state lval typ loc = + let process_one_loc = eval_one_loc state lval typ in + let acc = Cvalue.V.bottom, None in + let value, alarms = Precise_locs.fold process_one_loc loc acc in + let alarms = match alarms with None -> Alarmset.none | Some a -> a in + (* The origin is set to false when the value stored in the memory has not + the same type as the read lvalue. In this case, we don't update the state + with the new value stemming from the evaluation, even if it has been + reduced, in order to not propagate incompatible type. *) + let incompatible_type = is_float value <> Cil.isFloatingType typ in + let origin = if incompatible_type then Some value else None in + let value = Cvalue_forward.reinterpret typ value in + if Cvalue.V.is_bottom value + then `Bottom, alarms + else `Value (value, origin), alarms + + (* Imprecise version for aggregate types that cvalues are unable to precisely + represent. The initialization alarms must remain sound, though. *) + let extract_aggregate_lval state lval _typ ploc = + let loc = Precise_locs.imprecise_location ploc in + match loc.Locations.size with + | Int_Base.Top -> `Value (Cvalue.V.top, None), Alarmset.all + | Int_Base.Value size -> + let offsm = Cvalue.Model.copy_offsetmap loc.Locations.loc size state in + match offsm with + | `Bottom -> `Bottom, Alarmset.none + | `Value offsm -> + let value = Cvalue.V_Offsetmap.find_imprecise_everywhere offsm in + let alarms = indeterminate_alarms lval value in + let v = Cvalue.V_Or_Uninitialized.get_v value in + let v = if Cvalue.V.is_bottom v then `Bottom else `Value (v, None) in + v, alarms + + let extract_lval ~oracle:_ _context state lval typ loc = + if Cil.isArithmeticOrPointerType typ + then extract_scalar_lval state lval typ loc + else extract_aggregate_lval state lval typ loc + + let backward_location state _lval typ precise_loc value = + let size = Precise_locs.loc_size precise_loc in + let upto = succ (Int_set.get_small_cardinal()) in + let loc = Precise_locs.imprecise_location precise_loc in + let eval_one_loc single_loc = + let v = Cvalue.Model.find state single_loc in + let v = Cvalue_forward.make_volatile ~typ v in + Cvalue_forward.reinterpret typ v + in + let process_ival base ival (acc_loc, acc_val as acc) = + let loc_bits = Locations.Location_Bits.inject base ival in + let single_loc = Locations.make_loc loc_bits size in + let v = eval_one_loc single_loc in + if Cvalue.V.intersects v value + then Locations.Location_Bits.join loc_bits acc_loc, Cvalue.V.join v acc_val + else acc + in + let fold_ival base ival acc = + if Ival.cardinal_is_less_than ival upto + then Ival.fold_enum (process_ival base) ival acc + else process_ival base ival acc + in + let fold_location loc acc = + try + let loc = loc.Locations.loc in + Locations.Location_Bits.fold_i fold_ival loc acc + with + Abstract_interp.Error_Top -> loc.Locations.loc, value + in + let acc = Locations.Location_Bits.bottom, Cvalue.V.bottom in + let loc_bits, value = fold_location loc acc in + if Locations.Location_Bits.is_bottom loc_bits + then `Bottom + else + let loc = Precise_locs.inject_location_bits loc_bits in + `Value (Precise_locs.make_precise_loc loc ~size, value) + + let reduce_further _state _expr _value = [] +end + +include Queries + +(* -------------------------------------------------------------------------- *) +(* Evaluation engine for the cvalue domain *) +(* -------------------------------------------------------------------------- *) + +module Value = struct + module Internal = struct + include Main_values.CVal + let structure = Abstract.Value.Leaf (key, (module Main_values.CVal)) + end + include Internal + include Structure.Open (Abstract.Value) (Internal) + let reduce t = t +end + +module Domain = struct + include Cvalue.Model + include Queries +end + +include Evaluation.Make (Value) (Main_locations.PLoc) (Domain) + +let lval_to_loc state lval = + let eval, _alarms = lvaluate ~for_writing:false state lval in + match eval with + | `Bottom -> Locations.loc_bottom + | `Value (_valuation, ploc, _typ) -> Precise_locs.imprecise_location ploc diff --git a/src/kernel_services/abstract_interp/value_types.ml b/src/plugins/eva/domains/cvalue/cvalue_queries.mli similarity index 71% rename from src/kernel_services/abstract_interp/value_types.ml rename to src/plugins/eva/domains/cvalue/cvalue_queries.mli index d7d070d20e3053df8e3337c8921a6b9bd037c536..e6f423f25439ab77a9e34a23988997122a5e948e 100644 --- a/src/kernel_services/abstract_interp/value_types.ml +++ b/src/plugins/eva/domains/cvalue/cvalue_queries.mli @@ -20,17 +20,18 @@ (* *) (**************************************************************************) -type 'a callback_result = - | Normal of 'a - | NormalStore of 'a * int - | Reuse of int +(** Implementation of domain queries for the cvalue domain. *) +include Abstract_domain.Queries + with type state = Cvalue.Model.t + and type value = Main_values.CVal.t + and type location = Main_locations.PLoc.location + and type origin = Main_values.CVal.t -type call_froms = (Function_Froms.froms * Locations.Zone.t) option +(** Evaluation engine specific to the cvalue domain. *) +include Evaluation_sig.S with type state := state + and type value := value + and type loc := location + and type origin := origin -type logic_dependencies = Locations.Zone.t Cil_datatype.Logic_label.Map.t - -(* -Local Variables: -compile-command: "make -C ../../.." -End: -*) +(** Evaluates the location of a lvalue in a given cvalue state. *) +val lval_to_loc: state -> Cil_types.lval -> Locations.location diff --git a/src/plugins/eva/domains/cvalue/cvalue_transfer.ml b/src/plugins/eva/domains/cvalue/cvalue_transfer.ml index 222f8bbe68349524dabe96f1d9b91d1ed3e1e438..007674371f657ba8bdca117a649689e86287b3be 100644 --- a/src/plugins/eva/domains/cvalue/cvalue_transfer.ml +++ b/src/plugins/eva/domains/cvalue/cvalue_transfer.ml @@ -204,10 +204,7 @@ let actualize_formals state arguments = List.fold_left treat_one_formal state arguments let start_call _stmt call _recursion _valuation state = - let with_formals = actualize_formals state call.arguments in - let stack_with_call = Eva_utils.current_call_stack () in - Db.Value.Call_Value_Callbacks.apply (with_formals, stack_with_call); - `Value with_formals + `Value (actualize_formals state call.arguments) let finalize_call stmt call _recursion ~pre:_ ~post:state = (* Deallocate memory allocated via alloca(). diff --git a/src/plugins/eva/domains/cvalue/locals_scoping.ml b/src/plugins/eva/domains/cvalue/locals_scoping.ml index ce41844e798d31a73797da73a637810395c92398..2e263ae8d1f369514c6351153e9628b3e8b0bc62 100644 --- a/src/plugins/eva/domains/cvalue/locals_scoping.ml +++ b/src/plugins/eva/domains/cvalue/locals_scoping.ml @@ -27,9 +27,9 @@ type clobbered_set = { mutable clob: Base.SetLattice.t } -let structural_descr = +let packed_descr = let open Structural_descr in - t_record [| Base.SetLattice.packed_descr |] + pack (t_record [| Base.SetLattice.packed_descr |]) let bottom () = { clob = Base.SetLattice.bottom } let top () = { clob = Base.SetLattice.top } diff --git a/src/plugins/eva/domains/cvalue/locals_scoping.mli b/src/plugins/eva/domains/cvalue/locals_scoping.mli index 274e3ea64d0991b14b936e847a82cbeaec21750f..abaf168a64d782eb7106b29bde409b2099d48271 100644 --- a/src/plugins/eva/domains/cvalue/locals_scoping.mli +++ b/src/plugins/eva/domains/cvalue/locals_scoping.mli @@ -30,7 +30,7 @@ type clobbered_set = { mutable clob: Base.SetLattice.t } -val structural_descr: Structural_descr.t +val packed_descr: Structural_descr.pack val bottom: unit -> clobbered_set val top: unit -> clobbered_set diff --git a/src/plugins/eva/dune b/src/plugins/eva/dune index a5aae82cd3584e41c471019a26e2bfd4477b48c1..589387e2eda9f3eec9800160bc5a89a1b7dd86fd 100644 --- a/src/plugins/eva/dune +++ b/src/plugins/eva/dune @@ -40,7 +40,8 @@ (public_name frama-c-eva.core) (flags -open Frama_c_kernel :standard -w -9 -alert -db_deprecated) (libraries frama-c.kernel frama-c-server.core) - (instrumentation (backend landmarks))) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx))) (plugin (name eva) @@ -74,7 +75,8 @@ (public_name frama-c-eva.numerors.core) (flags -open Frama_c_kernel -open Eva__Private :standard) (libraries frama-c.kernel frama-c-eva.core mlmpfr) - (instrumentation (backend landmarks)))) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)))) (plugin (name eva.numerors) @@ -92,7 +94,8 @@ (libraries frama-c.kernel frama-c-eva.core apron.octMPQ apron.boxMPQ apron.polkaMPQ apron.apron) - (instrumentation (backend landmarks)))) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)))) (plugin (name eva.apron) diff --git a/src/plugins/eva/engine/analysis.ml b/src/plugins/eva/engine/analysis.ml index a93c6903e27d182ab6bc564fa6a3b82ae951c8ad..6bbfef27ba4dc1a948398cb182431dd2c0fda689 100644 --- a/src/plugins/eva/engine/analysis.ml +++ b/src/plugins/eva/engine/analysis.ml @@ -187,6 +187,8 @@ let cvalue_initial_state () = let _, lib_entry = Globals.entry_point () in G.get_cvalue_or_bottom (A.initial_state ~lib_entry) +let () = Db.Value.initial_state_only_globals := cvalue_initial_state + (* Builds the Analyzer module corresponding to a given configuration, and sets it as the current analyzer. *) let make_analyzer config = @@ -207,6 +209,12 @@ let reset_analyzer () = if not (Abstractions.Config.equal config (fst !ref_analyzer)) then make_analyzer config +(* Resets the Analyzer when the current project is changed. *) +let () = + Project.register_after_set_current_hook + ~user_only:true (fun _ -> reset_analyzer ()); + Project.register_after_global_load_hook reset_analyzer + (* Builds the analyzer if needed, and run the analysis. *) let force_compute () = Ast.compute (); @@ -230,8 +238,12 @@ let compute = let name = "Eva.Analysis.compute" in fst (State_builder.apply_once name [ Self.state ] compute) -(* Resets the Analyzer when the current project is changed. *) -let () = - Project.register_after_set_current_hook - ~user_only:true (fun _ -> reset_analyzer ()); - Project.register_after_global_load_hook reset_analyzer +let () = Db.Value.compute := compute +let () = Parameters.ForceValues.set_output_dependencies [Self.state] + +let main () = + (* Value computations *) + if Parameters.ForceValues.get () then compute (); + if is_computed () then Red_statuses.report () + +let () = Db.Main.extend main diff --git a/src/plugins/eva/engine/analysis.mli b/src/plugins/eva/engine/analysis.mli index 8dd74f365d0902882070a351b18b404853d35eef..fe482f514af1c500e3757d6505f5dc40adc3c5f7 100644 --- a/src/plugins/eva/engine/analysis.mli +++ b/src/plugins/eva/engine/analysis.mli @@ -154,6 +154,3 @@ val use_spec_instead_of_definition: Cil_types.kernel_function -> bool to known whether results are available for a given function. *) val save_results: Cil_types.kernel_function -> bool [@@@ api_end] - -val cvalue_initial_state: unit -> Cvalue.Model.t -(** Return the initial state of the cvalue domain only. *) diff --git a/src/plugins/eva/engine/compute_functions.ml b/src/plugins/eva/engine/compute_functions.ml index 9fda306efa9a0cafb74be4405962cf7d244a63ce..03dc9b5a62980335cac260fe0a35c8d5e8c0c418 100644 --- a/src/plugins/eva/engine/compute_functions.ml +++ b/src/plugins/eva/engine/compute_functions.ml @@ -353,16 +353,11 @@ module Make (Abstract: Abstractions.S_with_evaluation) = struct (* ----- Main call -------------------------------------------------------- *) - let store_initial_state callstack kf init_state = - Abstract.Dom.Store.register_initial_state callstack kf init_state; - let cvalue_state = get_cvalue_or_top init_state in - Db.Value.Call_Value_Callbacks.apply (cvalue_state, callstack) - let compute kf init_state = let restore_signals = register_signal_handler () in let compute () = let callstack = Eva_utils.init_call_stack kf in - store_initial_state callstack kf init_state; + Abstract.Dom.Store.register_initial_state callstack kf init_state; let call = { kf; callstack; arguments = []; rest = []; return = None; } in let final_result = compute_call Kglobal call None init_state in let final_states = List.map snd (final_result.Transfer.states) in diff --git a/src/plugins/eva/engine/iterator.ml b/src/plugins/eva/engine/iterator.ml index e97c859d276e889eadf25f1374727816f36479fa..28a09aefb91ba4effb0aa2d49f0ee2a97f5c8e6f 100644 --- a/src/plugins/eva/engine/iterator.ml +++ b/src/plugins/eva/engine/iterator.ml @@ -35,7 +35,6 @@ let check_signals, signal_abort = (fun () -> signal_emitted := true) let dkey = Self.dkey_iterator -let dkey_callbacks = Self.dkey_callbacks let stat_iterations = Statistics.register_statement_stat "iterations" let blocks_share_locals b1 b2 = @@ -686,13 +685,6 @@ module Make_Dataflow let merged_post_states = lazy (states_after_stmt merged_pre_states merged_post_states) in - let unmerged_pre_cvalues = lazy - (StmtTable.map (fun _stmt (v,_) -> - let store = get_vertex_store v in - let states = Partitioning.expanded store in - List.map (fun (_k,x) -> get_cvalue_or_top x) states) - automaton.stmt_table) - in let merged_pre_cvalues = lazy (lift_to_cvalues merged_pre_states) and merged_post_cvalues = lazy (lift_to_cvalues merged_post_states) in let callstack = Eva_utils.current_call_stack () in @@ -703,22 +695,6 @@ module Make_Dataflow StmtTable.iter register_post (Lazy.force merged_post_states); merge_conditions (); end; - if not (Db.Value.Record_Value_Superposition_Callbacks.is_empty ()) - then begin - if Parameters.ValShowProgress.get () then - Self.debug ~dkey:dkey_callbacks - "now calling Record_Value_Superposition callbacks"; - Db.Value.Record_Value_Superposition_Callbacks.apply - (callstack, unmerged_pre_cvalues); - end; - if not (Db.Value.Record_Value_Callbacks.is_empty ()) - then begin - if Parameters.ValShowProgress.get () then - Self.debug ~dkey:dkey_callbacks - "now calling Record_Value callbacks"; - Db.Value.Record_Value_Callbacks.apply - (callstack, merged_pre_cvalues) - end; let states = Cvalue_callbacks.{ before_stmts = merged_pre_cvalues; after_stmts = merged_post_cvalues } @@ -726,14 +702,6 @@ module Make_Dataflow let cvalue_init = get_cvalue_or_top initial_state in let results = `Body (states, Mem_exec.new_counter ()) in Cvalue_callbacks.apply_call_results_hooks callstack kf cvalue_init results; - if not (Db.Value.Record_Value_After_Callbacks.is_empty ()) - then begin - if Parameters.ValShowProgress.get () then - Self.debug ~dkey:dkey_callbacks - "now calling Record_After_Value callbacks"; - Db.Value.Record_Value_After_Callbacks.apply - (callstack, merged_post_cvalues); - end; end diff --git a/src/plugins/eva/engine/transfer_stmt.ml b/src/plugins/eva/engine/transfer_stmt.ml index 75e3571534fd65d3b671950aa9250ccfcb87ed59..78ab84bc9725887ee9d3ce1810e128248af25ce5 100644 --- a/src/plugins/eva/engine/transfer_stmt.ml +++ b/src/plugins/eva/engine/transfer_stmt.ml @@ -733,7 +733,6 @@ module Make (Abstract: Abstractions.S_with_evaluation) = struct let call_stack = Eva_utils.current_call_stack () in let stack_with_call = Callstack.push kf stmt call_stack in let cvalue_state = get_cvalue_or_top state in - Db.Value.Call_Value_Callbacks.apply (cvalue_state, stack_with_call); Cvalue_callbacks.apply_call_hooks stack_with_call kf cvalue_state `Builtin; Cvalue_callbacks.apply_call_results_hooks stack_with_call kf cvalue_state (`Builtin ([cvalue_state], None)) diff --git a/src/plugins/eva/legacy/function_args.ml b/src/plugins/eva/legacy/function_args.ml deleted file mode 100644 index b1f4dd23053f3a49a56eccdd76ff835d4b8376e6..0000000000000000000000000000000000000000 --- a/src/plugins/eva/legacy/function_args.ml +++ /dev/null @@ -1,83 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types -open Lattice_bounds - -exception Actual_is_bottom -exception WrongFunctionType (* at a call through a pointer *) - -let rec fold_left2_best_effort f acc l1 l2 = - match l1,l2 with - | _,[] -> acc - | [],_ -> raise WrongFunctionType (* Too few arguments *) - | (x1::r1),(x2::r2) -> fold_left2_best_effort f (f acc x1 x2) r1 r2 - -let actualize_formals kf state actuals = - let formals = Kernel_function.get_formals kf in - let treat_one_formal acc actual_o formal = - Cvalue.Model.add_base (Base.of_varinfo formal) actual_o acc - in - fold_left2_best_effort treat_one_formal state actuals formals - -let offsetmap_of_lv state lv = - let open Locations in - let state, loc_to_read, _typ = !Db.Value.lval_to_precise_loc_state state lv in - let aux loc offsm_res = - let size = Int_Base.project loc.size in - let copy = Cvalue.Model.copy_offsetmap loc.loc size state in - Bottom.join Cvalue.V_Offsetmap.join copy offsm_res - in - Precise_locs.fold aux loc_to_read `Bottom - -let compute_actual state e = - match e with - | { enode = Lval lv } when not (Eval_typ.is_bitfield (Cil.typeOfLval lv)) -> - let o = - try offsetmap_of_lv state lv - with Abstract_interp.Error_Top -> - Self.abort ~current:true - "Function argument %a has unknown size. Aborting" Printer.pp_exp e; - in begin - match o with - | `Value o -> o - | `Bottom -> raise Actual_is_bottom - end - | _ -> - let interpreted_expr = !Db.Value.eval_expr state e in - if Cvalue.V.is_bottom interpreted_expr then raise Actual_is_bottom; - let typ = Cil.typeOf e in - Eval_op.offsetmap_of_v ~typ interpreted_expr - -let () = - Db.Value.add_formals_to_state := - (fun state kf exps -> - try - let actuals = List.map (fun e -> compute_actual state e) exps in - actualize_formals kf state actuals - with Actual_is_bottom | WrongFunctionType -> Cvalue.Model.bottom) - -(* -Local Variables: -compile-command: "make -C ../../../.." -End: -*) diff --git a/src/plugins/eva/legacy/function_args.mli b/src/plugins/eva/legacy/function_args.mli deleted file mode 100644 index c2690f3b81659bccfa182f636ed5b8851db004ca..0000000000000000000000000000000000000000 --- a/src/plugins/eva/legacy/function_args.mli +++ /dev/null @@ -1,24 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Nothing is exported; the function [compute_atual] is registered - in {!Db.Value}. *) diff --git a/src/plugins/eva/register.ml b/src/plugins/eva/register.ml deleted file mode 100644 index 0994d6ee1ec9087820633e00d0d76eb0352e4ea2..0000000000000000000000000000000000000000 --- a/src/plugins/eva/register.ml +++ /dev/null @@ -1,447 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types -open Locations - -let () = Db.Value.compute := Analysis.compute -let () = Parameters.ForceValues.set_output_dependencies [Self.state] - -let main () = - (* Value computations *) - if Parameters.ForceValues.get () then Analysis.compute (); - if Analysis.is_computed () then Red_statuses.report () - -let () = Db.Main.extend main - - -(* "access" functions before evaluation, registered in Db.Value *) -let access_value_of_lval kinstr lv = - let state = Db.Value.get_state kinstr in - snd (!Db.Value.eval_lval None state lv) - -let access_value_of_expr kinstr e = - let state = Db.Value.get_state kinstr in - !Db.Value.eval_expr state e - -let access_value_of_location kinstr loc = - let state = Db.Value.get_state kinstr in - Db.Value.find state loc - -let find_deps_term_no_transitivity_state state t = - try - let env = Eval_terms.env_only_here state in - let r = Eval_terms.eval_term ~alarm_mode:Eval_terms.Ignore env t in - r.Eval_terms.ldeps - with Eval_terms.LogicEvalError _ -> raise Db.From.Not_lval - -let find_deps_no_transitivity stmt expr = - Results.(before stmt |> expr_deps expr) - -let find_deps_no_transitivity_state state expr = - Results.(in_cvalue_state state |> expr_deps expr) - -let eval_predicate ~pre ~here p = - let open Eval_terms in - let env = env_annot ~pre ~here () in - match eval_predicate env p with - | True -> Property_status.True - | False -> Property_status.False_if_reachable - | Unknown -> Property_status.Dont_know - -let () = - Db.Value.is_called := Function_calls.is_called; - Db.Value.callers := Function_calls.callsites; - Db.Value.use_spec_instead_of_definition := - Function_calls.use_spec_instead_of_definition; - Db.Value.assigns_outputs_to_zone := - (fun s ~result a -> Logic_inout.assigns_outputs_to_zone ~result s a); - Db.Value.assigns_inputs_to_zone := Logic_inout.assigns_inputs_to_zone; - Db.Value.access := access_value_of_lval; - Db.Value.access_location := access_value_of_location; - Db.Value.access_expr := access_value_of_expr; - Db.Value.Logic.eval_predicate := eval_predicate; - Db.Value.valid_behaviors := Logic_inout.valid_behaviors; - Db.From.find_deps_term_no_transitivity_state := - find_deps_term_no_transitivity_state; - Db.From.find_deps_no_transitivity := find_deps_no_transitivity; - Db.From.find_deps_no_transitivity_state := find_deps_no_transitivity_state; - - - (* -------------------------------------------------------------------------- *) - (* Register Evaluation Functions *) - (* -------------------------------------------------------------------------- *) - -open Eval - -module CVal = struct - include Main_values.CVal - let structure = Abstract.Value.Leaf (key, (module Main_values.CVal)) -end - -module Val = struct - include CVal - include Structure.Open (Abstract.Value) (CVal) - let reduce t = t -end - -module Eva = - Evaluation.Make - (Val) - (Main_locations.PLoc) - (Cvalue_domain.State) - -let inject_cvalue state = state, Locals_scoping.bottom () - -let bot_value = function - | `Bottom -> Cvalue.V.bottom - | `Value v -> v - -let bot_state = function - | `Bottom -> Cvalue.Model.bottom - | `Value s -> s - -let update valuation state = - let domain_valuation = Eva.to_domain_valuation valuation in - bot_state (Cvalue_domain.State.update domain_valuation state >>-: fst) - -let rec eval_deps state e = - match e.enode with - | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ | Const _ -> - Locations.Zone.bottom - | Lval lv -> eval_deps_lval state lv - | BinOp (_,e1,e2,_) -> - Locations.Zone.join (eval_deps state e1) (eval_deps state e2) - | CastE (_,e) | UnOp (_,e,_) -> - eval_deps state e - | AddrOf lv | StartOf lv -> eval_deps_addr state lv -and eval_deps_lval state lv = - let for_writing = false in - let deps = eval_deps_addr state lv in - let loc = - fst (Eva.lvaluate ~for_writing state lv) - >>-: fun (_valuation, loc, _typ) -> loc - in - match loc with - | `Bottom -> deps - | `Value loc -> - let deps_lv = Precise_locs.enumerate_valid_bits Read loc in - Locations.Zone.join deps deps_lv -and eval_deps_addr state (h, o:lval) = - Locations.Zone.join (eval_deps_host state h) (eval_deps_offset state o) -and eval_deps_host state h = match h with - | Var _ -> Locations.Zone.bottom - | Mem e -> eval_deps state e -and eval_deps_offset state o = match o with - | NoOffset -> Locations.Zone.bottom - | Field (_, o) -> eval_deps_offset state o - | Index (i, o) -> - Locations.Zone.join (eval_deps state i) (eval_deps_offset state o) - -let notify_opt with_alarms alarms = - Option.iter (fun mode -> Alarmset.notify mode alarms) with_alarms - -let eval_expr_with_valuation ?with_alarms deps state expr= - let state = inject_cvalue state in - let deps = match deps with - | None -> None - | Some deps -> - let deps' = eval_deps state expr in - Some (Locations.Zone.join deps' deps) - in - let eval, alarms = Eva.evaluate state expr in - notify_opt with_alarms alarms; - match eval with - | `Bottom -> (Cvalue.Model.bottom, deps, Cvalue.V.bottom), None - | `Value (valuation, result) -> - let state = update valuation state in - (state, deps, result), Some valuation - -(* Compatibility layer between the old API of eval_exprs and the new evaluation - scheme. *) -module Eval = struct - - let eval_expr ?with_alarms state expr = - let state = inject_cvalue state in - let eval, alarms = Eva.evaluate ~reduction:false state expr in - notify_opt with_alarms alarms; - bot_value (eval >>-: snd) - - let eval_lval ?with_alarms deps state lval = - let expr = Eva_utils.lval_to_exp lval in - let res, valuation = eval_expr_with_valuation ?with_alarms deps state expr in - let typ = match valuation with - | None -> Cil.typeOfLval lval - | Some valuation -> match Eva.Valuation.find_loc valuation lval with - | `Value record -> record.typ - | `Top -> Cil.typeOfLval lval - in - let state, deps, v = res in - state, deps, v, typ - - let eval_expr_with_deps_state ?with_alarms deps state expr = - fst (eval_expr_with_valuation ?with_alarms deps state expr) - - - let reduce_by_cond state expr positive = - let state = inject_cvalue state in - let eval, _alarms = - Eva.reduce state expr positive - in - bot_state (eval >>-: fun valuation -> update valuation state) - - - let lval_to_precise_loc_deps_state ?with_alarms ~deps state ~reduce_valid_index:(_:bool) lval = - if not (Cvalue.Model.is_reachable state) - then state, deps, Precise_locs.loc_bottom, (Cil.typeOfLval lval) - else - let state = inject_cvalue state in - let deps = match deps with - | None -> None - | Some deps -> - let deps' = eval_deps_addr state lval in - Some (Locations.Zone.join deps' deps) - in - let eval, alarms = - Eva.lvaluate ~for_writing:false state lval - in - notify_opt with_alarms alarms; - match eval with - | `Bottom -> Cvalue.Model.bottom, deps, Precise_locs.loc_bottom, (Cil.typeOfLval lval) - | `Value (valuation, loc, typ) -> update valuation state, deps, loc, typ - - let lval_to_loc_deps_state ?with_alarms ~deps state ~reduce_valid_index lv = - let state, deps, pl, typ = - lval_to_precise_loc_deps_state - ?with_alarms ~deps state ~reduce_valid_index lv - in - state, deps, Precise_locs.imprecise_location pl, typ - - let lval_to_precise_loc_state ?with_alarms state lv = - let state, _, r, typ = - lval_to_precise_loc_deps_state - ?with_alarms ~deps:None ~reduce_valid_index:(Kernel.SafeArrays.get ()) - state lv - in - state, r, typ - - and lval_to_loc_state ?with_alarms state lv = - let state, _, r, typ = - lval_to_loc_deps_state - ?with_alarms ~deps:None ~reduce_valid_index:(Kernel.SafeArrays.get ()) - state lv - in - state, r, typ - - let lval_to_precise_loc ?with_alarms state lv = - let _, r, _typ = lval_to_precise_loc_state ?with_alarms state lv in - r - - let lval_to_loc ?with_alarms state lv = - let _, r, _typ = lval_to_loc_state ?with_alarms state lv in - r - - - let resolv_func_vinfo ?with_alarms deps state funcexp = - let open Cil_types in - let state = inject_cvalue state in - let deps = match funcexp.enode with - | Lval (Var _, NoOffset) -> deps - | Lval (Mem v, _) -> - begin match deps with - | None -> None - | Some deps -> - let deps' = eval_deps state v in - Some (Locations.Zone.join deps' deps) - end - | _ -> assert false - in - let kfs, alarms = Eva.eval_function_exp funcexp state in - notify_opt with_alarms alarms; - let kfs = match kfs with - | `Bottom -> Kernel_function.Hptset.empty - | `Value kfs -> - List.fold_left - (fun acc (kf, _) -> Kernel_function.Hptset.add kf acc) - Kernel_function.Hptset.empty kfs - in - kfs, deps - -end - -module type Eval = module type of Eval - -(* Functions to register in Db.Value that depend on evaluation functions. *) -module Export (Eval : Eval) = struct - - open Eval - - let lval_to_loc_with_deps_state ?with_alarms state ~deps lv = - let _state, deps, r, _ = - lval_to_loc_deps_state - ?with_alarms - ~deps:(Some deps) - ~reduce_valid_index:(Kernel.SafeArrays.get ()) - state - lv - in - Option.value ~default:Locations.Zone.bottom deps, r - - let lval_to_loc_with_deps kinstr ?with_alarms ~deps lv = - let state = Db.Value.noassert_get_state kinstr in - lval_to_loc_with_deps_state ?with_alarms state ~deps lv - - let lval_to_loc_kinstr kinstr ?with_alarms lv = - let state = Db.Value.noassert_get_state kinstr in - lval_to_loc ?with_alarms state lv - - let lval_to_precise_loc_with_deps_state_alarm ?with_alarms state ~deps lv = - let _state, deps, ploc, _ = - lval_to_precise_loc_deps_state ?with_alarms - ~deps ~reduce_valid_index:(Kernel.SafeArrays.get ()) state lv - in - let deps = Option.value ~default:Locations.Zone.bottom deps in - deps, ploc - - let lval_to_precise_loc_with_deps_state = - lval_to_precise_loc_with_deps_state_alarm ?with_alarms:None - - let lval_to_zone kinstr ?with_alarms lv = - let state_to_joined_zone state acc = - let _, r = - lval_to_precise_loc_with_deps_state_alarm ?with_alarms state ~deps:None lv - in - let zone = Precise_locs.enumerate_valid_bits Read r in - Locations.Zone.join acc zone - in - Db.Value.fold_state_callstack - state_to_joined_zone Locations.Zone.bottom ~after:false kinstr - - let lval_to_zone_state state lv = - let _, r = lval_to_precise_loc_with_deps_state state ~deps:None lv in - Precise_locs.enumerate_valid_bits Read r - - let lval_to_zone_with_deps_state state ~for_writing ~deps lv = - let deps, r = lval_to_precise_loc_with_deps_state state ~deps lv in - let r = (* No write effect if [lv] is const *) - if for_writing && (Eva_utils.is_const_write_invalid (Cil.typeOfLval lv)) - then Precise_locs.loc_bottom - else r - in - let access = if for_writing then Write else Read in - let zone = Precise_locs.enumerate_valid_bits access r in - let exact = Precise_locs.valid_cardinal_zero_or_one ~for_writing r in - deps, zone, exact - - - let lval_to_offsetmap_aux ?with_alarms state lv = - let loc = - Locations.valid_part Read - (lval_to_loc ?with_alarms state lv) - in - match loc.Locations.size with - | Int_Base.Top -> None - | Int_Base.Value size -> - match Cvalue.Model.copy_offsetmap loc.Locations.loc size state with - | `Bottom -> None - | `Value m -> Some m - - let lval_to_offsetmap kinstr ?with_alarms lv = - let state = Db.Value.noassert_get_state kinstr in - lval_to_offsetmap_aux ?with_alarms state lv - - let lval_to_offsetmap_state state lv = - lval_to_offsetmap_aux state lv - - - let expr_to_kernel_function_state ?with_alarms state ~deps exp = - let r, deps = resolv_func_vinfo ?with_alarms deps state exp in - Option.value ~default:Locations.Zone.bottom deps, r - - let expr_to_kernel_function kinstr ?with_alarms ~deps exp = - let state_to_joined_kernel_function state (z_acc, kf_acc) = - let z, kf = - expr_to_kernel_function_state ?with_alarms state ~deps exp - in - Locations.Zone.join z z_acc, - Kernel_function.Hptset.union kf kf_acc - in - Db.Value.fold_state_callstack - state_to_joined_kernel_function - ((match deps with None -> Locations.Zone.bottom | Some z -> z), - Kernel_function.Hptset.empty) - ~after:false kinstr - - let expr_to_kernel_function_state = - expr_to_kernel_function_state ?with_alarms:None -end - - -module type Export = module type of (Export (Eval)) - -let register (module Eval: Eval) (module Export: Export) = - let open Export in - Db.Value.eval_expr := Eval.eval_expr; - Db.Value.eval_expr_with_state := - (fun ?with_alarms state expr -> - let (s, _, v) = - Eval.eval_expr_with_deps_state ?with_alarms None state expr - in - s, v); - Db.Value.reduce_by_cond := Eval.reduce_by_cond; - Db.Value.eval_lval := - (fun ?with_alarms deps state lval -> - let _, deps, r, _ = Eval.eval_lval ?with_alarms deps state lval in - deps, r); - Db.Value.lval_to_loc_with_deps := lval_to_loc_with_deps; - Db.Value.lval_to_loc_with_deps_state := - lval_to_loc_with_deps_state ?with_alarms:None; - Db.Value.lval_to_loc := lval_to_loc_kinstr; - Db.Value.lval_to_loc_state := Eval.lval_to_loc ?with_alarms:None; - Db.Value.lval_to_zone_state := lval_to_zone_state; - Db.Value.lval_to_zone := lval_to_zone; - Db.Value.lval_to_zone_with_deps_state := lval_to_zone_with_deps_state; - Db.Value.lval_to_precise_loc_state := Eval.lval_to_precise_loc_state; - Db.Value.lval_to_precise_loc_with_deps_state := - lval_to_precise_loc_with_deps_state; - Db.Value.lval_to_offsetmap := lval_to_offsetmap; - Db.Value.lval_to_offsetmap_state := lval_to_offsetmap_state; - Db.Value.expr_to_kernel_function := expr_to_kernel_function; - Db.Value.expr_to_kernel_function_state := expr_to_kernel_function_state; - () - - -let () = Db.Value.initial_state_only_globals := Analysis.cvalue_initial_state - -let () = Db.Value.verify_assigns_froms := Logic_inout.verify_assigns - -let () = - let eval = (module Eval : Eval) in - let export = (module Export ((val eval : Eval)) : Export) in - register eval export;; - - -(* -Local Variables: -compile-command: "make -C ../../.." -End: -*) diff --git a/src/plugins/eva/register.mli b/src/plugins/eva/register.mli deleted file mode 100644 index 3898a7c5ac07923fdae7ad7914c1dcbd1322a25b..0000000000000000000000000000000000000000 --- a/src/plugins/eva/register.mli +++ /dev/null @@ -1,28 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Functions of the Value plugin registered in {!Db}. Only three functions - are exported. *) - -val eval_deps : Cvalue_domain.State.t -> Cil_types.exp -> Locations.Zone.t -val eval_deps_lval : Cvalue_domain.State.t -> Cil_types.lval -> Locations.Zone.t -val eval_deps_addr : Cvalue_domain.State.t -> Cil_types.lval -> Locations.Zone.t diff --git a/src/plugins/eva/utils/cvalue_callbacks.ml b/src/plugins/eva/utils/cvalue_callbacks.ml index d5bf54e2f5b77bc048ad80777e94aa85cc0e2c81..d4101a12b9c2de6f3a289deef62458ba3a3ef6c6 100644 --- a/src/plugins/eva/utils/cvalue_callbacks.ml +++ b/src/plugins/eva/utils/cvalue_callbacks.ml @@ -39,15 +39,15 @@ let register_call_hook f = Call.extend (fun (callstack, kf, kind, state) -> f callstack kf kind state) let apply_call_hooks callstack kf state kind = - Call.apply (callstack, kf, state, kind); - Db.Value.Call_Type_Value_Callbacks.apply (kind, state, callstack) + Call.apply (callstack, kf, state, kind) +type call_froms = (Function_Froms.froms * Locations.Zone.t) option type state_by_stmt = (state Cil_datatype.Stmt.Hashtbl.t) Lazy.t type results = { before_stmts: state_by_stmt; after_stmts: state_by_stmt } type call_results = - [ `Builtin of state list * Value_types.call_froms + [ `Builtin of state list * call_froms | `Spec of state list | `Body of results * int | `Reuse of int @@ -65,21 +65,9 @@ let register_call_results_hook f = (fun (callstack, kf, state, results) -> f callstack kf state results) let apply_call_results_hooks callstack kf state call_results = - if Parameters.ValShowProgress.get () - && not (Call_Results.is_empty () - && Db.Value.Record_Value_Callbacks_New.is_empty ()) + if Parameters.ValShowProgress.get () && not (Call_Results.is_empty ()) then Self.debug ~dkey "now calling Call_Results callbacks"; - Call_Results.apply (callstack, kf, state, call_results); - let results = - match call_results with - | `Builtin _ | `Spec _ -> None - | `Reuse i -> Some (Value_types.Reuse i) - | `Body ({before_stmts; after_stmts}, i) -> - Some (Value_types.NormalStore ((before_stmts, after_stmts), i)) - in - Option.iter - (fun r -> Db.Value.Record_Value_Callbacks_New.apply (callstack, r)) - results + Call_Results.apply (callstack, kf, state, call_results) module Statement = @@ -89,5 +77,4 @@ let register_statement_hook f = Statement.extend (fun (callstack, stmt, states) -> f callstack stmt states) let apply_statement_hooks callstack stmt states = - Statement.apply (callstack, stmt, states); - Db.Value.Compute_Statement_Callbacks.apply (stmt, callstack, states) + Statement.apply (callstack, stmt, states) diff --git a/src/plugins/eva/utils/cvalue_callbacks.mli b/src/plugins/eva/utils/cvalue_callbacks.mli index 52d0d41330f31893650a9a232d2173376ea029bc..baa6dc0942ac19de3ec39a0ce11584b893626fe8 100644 --- a/src/plugins/eva/utils/cvalue_callbacks.mli +++ b/src/plugins/eva/utils/cvalue_callbacks.mli @@ -30,6 +30,11 @@ type state = Cvalue.Model.t +(** If not None, the froms of the function, and its sure outputs; + i.e. the dependencies of the result, and the dependencies + of each zone written to. *) +type call_froms = (Function_Froms.froms * Locations.Zone.t) option + type analysis_kind = [ `Builtin (** A cvalue builtin is used to interpret the function. *) | `Spec (** The specification is used to interpret the function. *) @@ -53,7 +58,7 @@ type results = { before_stmts: state_by_stmt; after_stmts: state_by_stmt } (** Results of a function call. *) type call_results = - [ `Builtin of state list * Value_types.call_froms + [ `Builtin of state list * call_froms (** List of cvalue states at the end of the builtin. *) | `Spec of state list (** List of cvalue states at the end of the call. *) diff --git a/src/plugins/eva/utils/eva_dynamic.ml b/src/plugins/eva/utils/eva_dynamic.ml index ebfdc9384ad7969a7b94b12b290d03c92ccc47f0..c623675e2d22d95923eb4b3a9817f0c91cd2a8ec 100644 --- a/src/plugins/eva/utils/eva_dynamic.ml +++ b/src/plugins/eva/utils/eva_dynamic.ml @@ -62,5 +62,6 @@ module RteGen = struct let mark_generated_rte () = let list = all_statuses () in let mark kf = List.iter (fun (_kind, set, _get) -> set kf true) list in - Globals.Functions.iter (fun kf -> if !Db.Value.is_called kf then mark kf) + Globals.Functions.iter + (fun kf -> if Function_calls.is_called kf then mark kf) end diff --git a/src/plugins/eva/utils/eva_utils.ml b/src/plugins/eva/utils/eva_utils.ml index 73dc03924ed0497f7e611994aeb9631803134333..1c3e435164f5ac9774c60b5390c7037c2061651d 100644 --- a/src/plugins/eva/utils/eva_utils.ml +++ b/src/plugins/eva/utils/eva_utils.ml @@ -79,8 +79,6 @@ let emitter = ~correctness:Parameters.parameters_correctness ~tuning:Parameters.parameters_tuning -let () = Db.Value.emitter := emitter - let get_slevel kf = try Parameters.SlevelFunction.find kf with Not_found -> Parameters.SemanticUnrollingLevel.get () diff --git a/src/plugins/eva/utils/widen.ml b/src/plugins/eva/utils/widen.ml index 00f6e6a4283eb02d0687521a5b4f732f7c8fcb52..b26bb71371f86aef95114f2fda4217a5348188b6 100644 --- a/src/plugins/eva/utils/widen.ml +++ b/src/plugins/eva/utils/widen.ml @@ -499,7 +499,7 @@ module Parsed_Dynamic_Hints = let dynamic_bases_of_lval states e offset = let lv = (Mem e, offset) in List.fold_left (fun acc' state -> - let location = !Db.Value.lval_to_loc_state state lv in + let location = Cvalue_queries.lval_to_loc state lv in Locations.Location_Bits.fold_bases (fun base acc'' -> Base.Hptset.add base acc'') location.Locations.loc acc' @@ -561,7 +561,7 @@ let extract_per_function_hints fdec = let per_function_hints = Per_Function_Hints.memo extract_per_function_hints -let dynamic_widen_hints_hook (stmt, _callstack, states) = +let dynamic_widen_hints_hook _callstack stmt states = if Annotations.has_code_annot stmt then let hs = parsed_dynamic_hints stmt in if hs <> [] then @@ -602,8 +602,7 @@ let dynamic_widen_hints_hook (stmt, _callstack, states) = Dynamic_Hints.set hints; end -let () = - Db.Value.Compute_Statement_Callbacks.extend_once dynamic_widen_hints_hook +let () = Cvalue_callbacks.register_statement_hook dynamic_widen_hints_hook let getWidenHints (kf:kernel_function) (stmt:stmt) = let hints = diff --git a/src/plugins/from/dune b/src/plugins/from/dune index 649a080ec4f499857fd6e2178031d85c6b19da56..1f4eab52cb87d4906ba5ec6760a46e7ab3416fc9 100644 --- a/src/plugins/from/dune +++ b/src/plugins/from/dune @@ -39,6 +39,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-callgraph.core frama-c-eva.core frama-c-postdominators.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name from) (libraries frama-c-from.core) (site (frama-c plugins))) diff --git a/src/plugins/impact/dune b/src/plugins/impact/dune index 8bd94fb058126db9ae356f0ef7b36b74197afc9a..418b94fb5eb56c55e22551ccddcb85f2a336d41b 100644 --- a/src/plugins/impact/dune +++ b/src/plugins/impact/dune @@ -41,6 +41,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-pdg.core frama-c-slicing.core frama-c-callgraph.core frama-c-inout.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name impact) (libraries frama-c-impact.core) (site (frama-c plugins))) diff --git a/src/plugins/inout/dune b/src/plugins/inout/dune index 1029fd27994ec0c1a67c497a521b3bac50572b90..9ed847d58dca23a18a7d18af687751c14a0516aa 100644 --- a/src/plugins/inout/dune +++ b/src/plugins/inout/dune @@ -39,6 +39,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-callgraph.core frama-c-eva.core frama-c-from.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name inout) (libraries frama-c-inout.core) (site (frama-c plugins))) diff --git a/src/plugins/instantiate/dune b/src/plugins/instantiate/dune index 61f0edbbea34f20a3a0fb38815f5510506feae54..d98fd93169c94947cde040c491a98b5bbf077b8f 100644 --- a/src/plugins/instantiate/dune +++ b/src/plugins/instantiate/dune @@ -36,6 +36,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name instantiate) (libraries frama-c-instantiate.core) (site (frama-c plugins))) diff --git a/src/plugins/loop_analysis/dune b/src/plugins/loop_analysis/dune index 178b00973e557e2fa7c0a05be661e70f77132072..266477032f1b50f9c79653a9cdc2fb5f62b56285 100644 --- a/src/plugins/loop_analysis/dune +++ b/src/plugins/loop_analysis/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name loop-analysis) (libraries frama-c-loop-analysis.core) (site (frama-c plugins))) diff --git a/src/plugins/markdown-report/dune b/src/plugins/markdown-report/dune index d09f77429709bca371b79c73a81d15cf917eefce..58cf7b1d43bef21c0612178cb7d08fa0c0976c03 100644 --- a/src/plugins/markdown-report/dune +++ b/src/plugins/markdown-report/dune @@ -38,6 +38,7 @@ (libraries frama-c.kernel) (preprocess (pps ppx_deriving_yojson)) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name markdown-report) (libraries frama-c-markdown-report.core) (site (frama-c plugins))) diff --git a/src/plugins/markdown-report/eva-info/dune b/src/plugins/markdown-report/eva-info/dune index 9d6d8395828a835e90f551da4f67067e54d5a970..6ea5596e04945496f2818323c29efe9eccbc50d5 100644 --- a/src/plugins/markdown-report/eva-info/dune +++ b/src/plugins/markdown-report/eva-info/dune @@ -39,6 +39,7 @@ (libraries frama-c.kernel frama-c-eva.core frama-c-markdown-report.core) (preprocess (pps ppx_deriving_yojson)) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name markdown-report.eva-info) (libraries frama-c-markdown-report.eva-info.core) (site (frama-c plugins))) diff --git a/src/plugins/metrics/dune b/src/plugins/metrics/dune index 04d94b067045dc9f4ce57d07191df87c7e464fea..4dc059de651db28f1581bd40ae537a6cf138426e 100644 --- a/src/plugins/metrics/dune +++ b/src/plugins/metrics/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core frama-c-server.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name metrics) (libraries frama-c-metrics.core) (site (frama-c plugins))) diff --git a/src/plugins/nonterm/dune b/src/plugins/nonterm/dune index b2273574bbbeb269cdc2ede7e4322982695fc689..7e65237e8986219f0a311538851bdc3a4384a11e 100644 --- a/src/plugins/nonterm/dune +++ b/src/plugins/nonterm/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name nonterm) (libraries frama-c-nonterm.core) (site (frama-c plugins))) diff --git a/src/plugins/obfuscator/dune b/src/plugins/obfuscator/dune index 94ea79b5e98427298d0f43ab58249671f0c8d229..af464f3364cc4bac758598800e7131ac1bc3dd4f 100644 --- a/src/plugins/obfuscator/dune +++ b/src/plugins/obfuscator/dune @@ -36,6 +36,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name obfuscator) (libraries frama-c-obfuscator.core) (site (frama-c plugins))) diff --git a/src/plugins/occurrence/dune b/src/plugins/occurrence/dune index e7364f769a2319955e666378d4c9c6917417c6e8..7afdbd4ac8aa78b9fcbd3644fc93d5d1eae028f4 100644 --- a/src/plugins/occurrence/dune +++ b/src/plugins/occurrence/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name occurrence) (libraries frama-c-occurrence.core) (site (frama-c plugins))) diff --git a/src/plugins/pdg/dune b/src/plugins/pdg/dune index 863c56b6e2de6a019d56b95e83fc21c8796e79c7..ef59c0a573c37994967fd9f8d327eab5ed11d0a3 100644 --- a/src/plugins/pdg/dune +++ b/src/plugins/pdg/dune @@ -40,6 +40,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-pdg.types.core frama-c-callgraph.core frama-c-from.core frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name pdg) (libraries frama-c-pdg.core) (site (frama-c plugins))) diff --git a/src/plugins/postdominators/dune b/src/plugins/postdominators/dune index 78bb8e11e3ebf71e1b64a21afdb6fbb040d8e047..6bcbe0cb1c77ffa55fccff8c6b57d6008edd4550 100644 --- a/src/plugins/postdominators/dune +++ b/src/plugins/postdominators/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name postdominators) (libraries frama-c-postdominators.core) (site (frama-c plugins))) diff --git a/src/plugins/qed/dune b/src/plugins/qed/dune index 2bac3d85858e21bf3acda8ff8f9d9449f11c00b0..7ab708cff07c260474742704375c3c6a9b320795 100644 --- a/src/plugins/qed/dune +++ b/src/plugins/qed/dune @@ -33,4 +33,5 @@ (public_name qed) (flags (-open Frama_c_kernel :standard -w -9)) (libraries frama-c.kernel zarith) - (instrumentation (backend landmarks))) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx))) diff --git a/src/plugins/reduc/dune b/src/plugins/reduc/dune index d95065487687c848e13aa3654a64d4a1ece01952..5e988de32a89f062c6fde4eb0285e4f700f18bfa 100644 --- a/src/plugins/reduc/dune +++ b/src/plugins/reduc/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-inout.core frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name reduc) (libraries frama-c-reduc.core) (site (frama-c plugins))) diff --git a/src/plugins/report/dune b/src/plugins/report/dune index e0d6da734381d40aff29038564b6118251c0357c..d13c79cc7ed3e19086fcaa781a50577073f8b505 100644 --- a/src/plugins/report/dune +++ b/src/plugins/report/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name report) (libraries frama-c-report.core) (site (frama-c plugins))) diff --git a/src/plugins/rte/dune b/src/plugins/rte/dune index d2ef8a04f8c50435c80e13ae42a28a7b1fea6d8a..d6212e907f0118c6f328dab14883bc8d3a2ef3cd 100644 --- a/src/plugins/rte/dune +++ b/src/plugins/rte/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name rtegen) (libraries frama-c-rtegen.core) (site (frama-c plugins))) diff --git a/src/plugins/scope/datascope.ml b/src/plugins/scope/datascope.ml index 513145d4b9f96e3016858c565b2c4176e932d7b0..f992fda8da2b72a2dc2d59a582b7fa832b201391 100644 --- a/src/plugins/scope/datascope.ml +++ b/src/plugins/scope/datascope.ml @@ -637,9 +637,6 @@ let rm_asserts () = CA_Map.iter aux to_be_removed end - -let () = Db.register Db.Value.rm_asserts rm_asserts [@alert "-db_deprecated"] - let rm_asserts = Dynamic.register ~comment:"Remove redundant alarms. Used by the Eva plugin." diff --git a/src/plugins/scope/dune b/src/plugins/scope/dune index 874c095e96cdafb17a43b2adba8a5ae42d075bd2..8bcbfda8750ecf4a2e6731d2634c909d1b208aa0 100644 --- a/src/plugins/scope/dune +++ b/src/plugins/scope/dune @@ -39,6 +39,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core frama-c-inout.core frama-c-pdg.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name scope) (libraries frama-c-scope.core) (site (frama-c plugins))) diff --git a/src/plugins/security_slicing/dune b/src/plugins/security_slicing/dune index e214e44e80cd92c233b339643d2cc1090a39b286..c54b7cb8820d41975d354c8e2fac3c62038ebaca 100644 --- a/src/plugins/security_slicing/dune +++ b/src/plugins/security_slicing/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-eva.core frama-c-pdg.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name security_slicing) (libraries frama-c-security_slicing.core) (site (frama-c plugins))) diff --git a/src/plugins/server/dune b/src/plugins/server/dune index 685cbacd1796d8ab5da67e7edaa70d1382c9ae8b..ff5efd4e2cad124c23a78a44bee412679689cf7e 100644 --- a/src/plugins/server/dune +++ b/src/plugins/server/dune @@ -41,6 +41,7 @@ ( -> server_zmq.ko.ml) )) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name server) (libraries frama-c-server.core) (site (frama-c plugins))) diff --git a/src/plugins/slicing/dune b/src/plugins/slicing/dune index a8c8753b1072312a5a538df7da1ac428dc8c9f1f..23df7d7c78f22a6323af17e578fa353b4e35501a 100644 --- a/src/plugins/slicing/dune +++ b/src/plugins/slicing/dune @@ -38,6 +38,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel frama-c-pdg.core frama-c-sparecode.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name slicing) (libraries frama-c-slicing.core) (site (frama-c plugins))) diff --git a/src/plugins/sparecode/dune b/src/plugins/sparecode/dune index 5764630f5cf926628b7514a8030da150a8751252..24bba5862e67904a689a51d4e4a8c46a50102954 100644 --- a/src/plugins/sparecode/dune +++ b/src/plugins/sparecode/dune @@ -41,6 +41,7 @@ (flags :standard -open Frama_c_kernel) (libraries frama-c.kernel frama-c-users.core frama-c-eva.core frama-c-pdg.core frama-c-inout.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name sparecode) (libraries frama-c-sparecode.core) (site (frama-c plugins))) diff --git a/src/plugins/studia/dune b/src/plugins/studia/dune index 841fcb9550f3922a0d4536be9475fbce65455deb..cb4cc468ce98a2b7a1559a7a72c75b9eebbaa98d 100644 --- a/src/plugins/studia/dune +++ b/src/plugins/studia/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard) (libraries frama-c.kernel frama-c-eva.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name studia) (libraries frama-c-studia.core) (site (frama-c plugins))) diff --git a/src/plugins/users/dune b/src/plugins/users/dune index 0f48402bedaf7da2495be36d1369f37df0ef1cd9..3bdf049483ba12ae10818bb061766d9c25538f91 100644 --- a/src/plugins/users/dune +++ b/src/plugins/users/dune @@ -37,6 +37,7 @@ (flags -open Frama_c_kernel :standard) (libraries frama-c.kernel frama-c-callgraph.core) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name users) (libraries frama-c-users.core) (site (frama-c plugins))) diff --git a/src/plugins/variadic/dune b/src/plugins/variadic/dune index fbd5f8dbde83ed0c866fb59ce32044f914f58926..573b69bdd08ee569948ed1bca825c221d5fd749a 100644 --- a/src/plugins/variadic/dune +++ b/src/plugins/variadic/dune @@ -36,6 +36,7 @@ (flags -open Frama_c_kernel :standard -w -9) (libraries frama-c.kernel) (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx)) ) (plugin (optional) (name variadic) (libraries frama-c-variadic.core) (site (frama-c plugins))) diff --git a/src/plugins/wp/Lang.ml b/src/plugins/wp/Lang.ml index e136f5b7960e00efa2cff1568f989eeca8077b4b..898e9209ba48c126c8e7cb0b384abc7066a3a183 100644 --- a/src/plugins/wp/Lang.ml +++ b/src/plugins/wp/Lang.ml @@ -908,7 +908,7 @@ open F module N = struct let ( + ) = e_add - let ( ~- ) x = e_sub e_zero x + let ( ~-: ) x = e_sub e_zero x let ( - ) = e_sub let ( * ) = e_mul let ( / ) = e_div @@ -922,8 +922,8 @@ module N = struct let ( <> ) = p_neq let ( ==> ) = p_imply - let ( && ) = p_and - let ( || ) = p_or + let ( &&: ) = p_and + let ( ||: ) = p_or let not = p_not let ( $ ) = e_fun diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli index bdb9af7a61b4e6c6f276457c569557b77e7f8a46..273b3dd5fde4e2060c0740435bc10874ffc4bff8 100644 --- a/src/plugins/wp/Lang.mli +++ b/src/plugins/wp/Lang.mli @@ -575,8 +575,11 @@ module N: sig val ( - ): F.binop (** {! F.p_sub } *) - val ( ~- ): F.unop - (** [fun x -> p_sub 0 x] *) + val ( ~-: ): F.unop + (** [fun x -> p_sub 0 x] + Beware that the operator does not have the same precedence as [~-] in + standard OCaml. + *) val ( * ): F.binop (** {! F.p_mul} *) @@ -610,11 +613,17 @@ module N: sig val ( ==> ): F.operator (** {! F.p_imply } *) - val ( && ): F.operator - (** {! F.p_and } *) - - val ( || ): F.operator - (** {! F.p_or } *) + val ( &&: ): F.operator + (** {! F.p_and } + Beware that the operator does not have the same precedence as [&&] + in standard OCaml. + *) + + val ( ||: ): F.operator + (** {! F.p_or } + Beware that the operator does not have the same precedence as [||] + in standard OCaml. + *) val not: F.pred -> F.pred (** {! F.p_not } *) diff --git a/src/plugins/wp/TacModMask.ml b/src/plugins/wp/TacModMask.ml index 2eb2b7d7a790ca8d28cf3581f6f4ab5e1121acb9..c2e7cd09ba2e358847157112f9845f147ca124c0 100644 --- a/src/plugins/wp/TacModMask.ml +++ b/src/plugins/wp/TacModMask.ml @@ -78,9 +78,9 @@ class modmask = let power_of_2 = let v = Lang.freshvar ~basename:"n" Lang.t_int in let tv = e_var v in - p_exists [v] (e_zero <= tv && m = Cint.l_lsl e_one tv) + p_exists [v] ((e_zero <= tv) &&: (m = Cint.l_lsl e_one tv)) in - let cond = (a >= e_zero && e_zero < m && power_of_2) in + let cond = ((a >= e_zero) &&: (e_zero < m) &&: power_of_2) in let n = Cint.l_and a (m - e_one) in update_display ~hard:true ~active_field:false ; @@ -106,9 +106,10 @@ class modmask = let plus_1_power_of_2 = let v = Lang.freshvar ~basename:"n" Lang.t_int in let tv = e_var v in - p_exists [v] (e_zero <= tv && m + e_one = Cint.l_lsl e_one tv) + p_exists [v] (e_zero <= tv &&: (m + e_one = Cint.l_lsl e_one tv)) in - let cond = (a >= e_zero && e_zero <= m && plus_1_power_of_2) in + let cond = + ((a >= e_zero) &&: (e_zero <= m) &&: (plus_1_power_of_2)) in let n = a mod (m + e_one) in update_display ~hard:true ~active_field:true ; diff --git a/src/plugins/wp/TacOverflow.ml b/src/plugins/wp/TacOverflow.ml index ec5701d77360ed98b54cb68bbe4b2feb4155e1e5..c28c055e8728f1793bed1d114fd0d559d22429c7 100644 --- a/src/plugins/wp/TacOverflow.ml +++ b/src/plugins/wp/TacOverflow.ml @@ -42,7 +42,7 @@ class overflow = let min, max = e_zint min, e_zint max in let lower = v < min and upper = max < v in - let in_range = not (lower || upper) in + let in_range = not (lower ||: upper) in let length = (max - min) + e_one in let overflow = min + ((v - min) mod length) in diff --git a/src/plugins/wp/dune b/src/plugins/wp/dune index 286e356130a20349b6cc7a1a80c1bf77f6b760ef..b72a5d06e70472b3b918bb63ef6dd8b10de5dcce 100644 --- a/src/plugins/wp/dune +++ b/src/plugins/wp/dune @@ -44,7 +44,8 @@ (select wp_eva.ml from (frama-c-eva.core -> wp_eva.enabled.ml) ( -> wp_eva.disabled.ml))) - (instrumentation (backend landmarks))) + (instrumentation (backend landmarks)) + (instrumentation (backend bisect_ppx))) (plugin (optional) (name wp) (libraries frama-c-wp.core) (site (frama-c plugins)))