Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cram tests for CFGs #1360

Merged
merged 25 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
55c9e5d
Add CFG test using graph-easy
sim642 Feb 9, 2024
3093d27
Use locations in CFG test nodes
sim642 Feb 9, 2024
b8c6e64
Use stdout for CFG test
sim642 Feb 9, 2024
d13a432
Use function names in CFG tests
sim642 Feb 9, 2024
48d4b63
Add cram tests for CFG
sim642 Feb 9, 2024
6ed1aae
Move some functions to CfgTools
sim642 Feb 9, 2024
b727532
Test CFGs per function
sim642 Feb 9, 2024
a1483d6
Fix instructions in CFG testing
sim642 Feb 9, 2024
361af13
More detailed location output in CFG tests
sim642 Feb 9, 2024
9036370
Merge branch 'master' into cfg-test
sim642 Feb 13, 2024
e81df45
Add test for synthetic witness invariant locations (PR #758)
sim642 Feb 13, 2024
7018ccf
Add test for incorrect witness invariant locations from CIL transform…
sim642 Feb 13, 2024
b734f50
Update CIL for synthetic locations fix
sim642 Feb 13, 2024
65ae0f0
Add graph-easy Ubuntu depext
sim642 Feb 13, 2024
de83ccc
Try to pin using with-test in CI
sim642 Feb 13, 2024
4d86fd0
Add enabled_if to CFG tests in 00-sanity as well
sim642 Feb 13, 2024
d48e85e
Try to pin using with-test in CI via opam-depext-flags
sim642 Feb 13, 2024
4b58d45
Try to pin using with-test in CI via hack
sim642 Feb 13, 2024
ae5b2cf
Install graph-easy manually in CI because nothing works
sim642 Feb 13, 2024
15e8ca3
Install graph-easy only on Ubuntu in CI
sim642 Feb 13, 2024
d146e9b
Update GobView for moved compute_cfg
sim642 Feb 14, 2024
b730994
Comment about depext --with-test
sim642 Feb 21, 2024
45e01c3
Extract CilCfg0
sim642 Feb 21, 2024
3f20225
Remove commented-out CilLocation.get_labelsLoc
sim642 Feb 21, 2024
5e65e22
Merge branch 'master' into cfg-test
sim642 Feb 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install dependencies
run: opam install . --deps-only --locked --with-test
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/locked.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install dependencies
run: opam install . --deps-only --locked --with-test
Expand Down Expand Up @@ -114,6 +119,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install spin
run: sudo apt-get -y install spin
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/unlocked.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install dependencies
run: opam install . --deps-only --with-test
Expand Down Expand Up @@ -139,6 +144,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install dependencies
run: opam install . --deps-only --with-test
Expand Down Expand Up @@ -255,6 +265,11 @@ jobs:
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
opam-depext-flags: --with-test # doesn't work (https://github.com/ocaml/opam/issues/5836)

- name: Install graph-easy # TODO: remove if depext --with-test works
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y libgraph-easy-perl

- name: Install Goblint with test
run: opam install goblint --with-test
Expand Down
5 changes: 4 additions & 1 deletion goblint.opam
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ dev-repo: "git+https://github.com/goblint/analyzer.git"
available: os-distribution != "alpine" & arch != "arm64"
pin-depends: [
# published goblint-cil 2.0.3 is currently up-to-date, so no pin needed
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#3cb720fe333289aca998d67bd210c57a87248c51" ]
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5" ]
# TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252)
[ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ]
]
depexts: [
["libgraph-easy-perl"] {os-distribution = "ubuntu" & with-test}
]
post-messages: [
"Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"}
]
3 changes: 2 additions & 1 deletion goblint.opam.locked
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,11 @@ post-messages: [
pin-depends: [
[
"goblint-cil.2.0.3"
"git+https://github.com/goblint/cil.git#3cb720fe333289aca998d67bd210c57a87248c51"
"git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5"
]
[
"ppx_deriving.5.2.1"
"git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6"
]
]
depexts: ["libgraph-easy-perl"] {os-distribution = "ubuntu" & with-test}
5 changes: 4 additions & 1 deletion goblint.opam.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
available: os-distribution != "alpine" & arch != "arm64"
pin-depends: [
# published goblint-cil 2.0.3 is currently up-to-date, so no pin needed
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#3cb720fe333289aca998d67bd210c57a87248c51" ]
[ "goblint-cil.2.0.3" "git+https://github.com/goblint/cil.git#833378d9102578bab7b62174cb029d385db417a5" ]
# TODO: add back after release, only pinned for optimization (https://github.com/ocaml-ppx/ppx_deriving/pull/252)
[ "ppx_deriving.5.2.1" "git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6" ]
]
depexts: [
["libgraph-easy-perl"] {os-distribution = "ubuntu" & with-test}
]
post-messages: [
"Do not benchmark Goblint on OCaml 5 (https://goblint.readthedocs.io/en/latest/user-guide/benchmarking/)." {ocaml:version >= "5.0.0"}
]
2 changes: 1 addition & 1 deletion gobview
6 changes: 6 additions & 0 deletions src/common/framework/cfgTools.ml
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,12 @@ let getCFG (file: file) : cfg * cfg * stmt list CfgEdgeH.t =
if get_bool "justcfg" then fprint_hash_dot cfgB;
(fun n -> H.find_default cfgF n []), (fun n -> H.find_default cfgB n []), skippedByEdge

let compute_cfg_skips file =
let cfgF, cfgB, skippedByEdge = getCFG file in
(module struct let prev = cfgB let next = cfgF end : CfgBidir), skippedByEdge

let compute_cfg file = fst (compute_cfg_skips file)


let iter_fd_edges (module Cfg : CfgBackward) fd =
let ready = NH.create 113 in
Expand Down
24 changes: 24 additions & 0 deletions src/common/util/cilCfg0.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
(** CIL CFG functions to avoid dependency problems. *)

open GoblintCil

class allBBVisitor = object (* puts every instruction into its own basic block *)
inherit nopCilVisitor
method! vstmt s =
match s.skind with
| Instr(il) ->
let list_of_stmts =
List.map (fun one_inst -> mkStmtOneInstr one_inst) il in
let block = mkBlock list_of_stmts in
ChangeDoChildrenPost(s, (fun _ -> s.skind <- Block(block); s))
| _ -> DoChildren

method! vvdec _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
end

let end_basic_blocks f =
let thisVisitor = new allBBVisitor in
visitCilFileSameGlobals thisVisitor f
45 changes: 45 additions & 0 deletions src/common/util/cilLocation.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
open GoblintCil

type locs = {
loc: location;
eloc: location;
}

let get_labelLoc = function
| Label (_, loc, _) -> {loc; eloc = locUnknown}
| Case (_, loc, eloc) -> {loc; eloc}
| CaseRange (_, _, loc, eloc) -> {loc; eloc}
| Default (loc, eloc) -> {loc; eloc}

(* TODO: need get_labelsLoc? *)

(** Following functions are similar to [Cil] versions, but return expression location instead of entire statement location, where possible. *)
(* Ideally we would have both copies of the functions available, but UpdateCil would have to be adapted per-stmtkind/instr to store and update either one or two locations. *)

(** Get locations for {!Cil.instr}. *)
let get_instrLoc = function
| Set (_, _, loc, eloc) -> {loc; eloc}
| Call (_, _, _, loc, eloc) -> {loc; eloc}
| Asm (_, _, _, _, _, loc) -> {loc; eloc = locUnknown}
| VarDecl (_, loc) -> {loc; eloc = locUnknown}

(** Get locations for {!Cil.stmt}. *)
(* confusingly {!Cil.get_stmtLoc} works on stmtkind instead *)
let rec get_stmtLoc stmt: locs =
match stmt.skind with
(* no stmtkind/instr location in these cases, so try labels instead *)
| Instr []
| Block {bstmts = []; _} ->
(* get_labelsLoc stmt.labels *)
{loc = locUnknown; eloc = locUnknown}

| Instr (hd :: _) -> get_instrLoc hd
| Return (_, loc) -> {loc; eloc = locUnknown}
| Goto (_, loc) -> {loc; eloc = locUnknown}
| ComputedGoto (_, loc) -> {loc; eloc = locUnknown}
| Break loc -> {loc; eloc = locUnknown}
| Continue loc -> {loc; eloc = locUnknown}
| If (_, _, _, loc, eloc) -> {loc; eloc}
| Switch (_, _, _, loc, eloc) -> {loc; eloc}
| Loop (_, loc, eloc, _, _) -> {loc; eloc}
| Block {bstmts = hd :: _; _} -> get_stmtLoc hd
8 changes: 1 addition & 7 deletions src/framework/control.ml
Original file line number Diff line number Diff line change
Expand Up @@ -806,15 +806,9 @@ let rec analyze_loop (module CFG : CfgBidir) file fs change_info skippedByEdge =
(* TODO: do some more incremental refinement and reuse parts of solution *)
analyze_loop (module CFG) file fs change_info skippedByEdge

let compute_cfg_skips file =
let cfgF, cfgB, skippedByEdge = CfgTools.getCFG file in
(module struct let prev = cfgB let next = cfgF end : CfgBidir), skippedByEdge

let compute_cfg = fst % compute_cfg_skips

(** The main function to perform the selected analyses. *)
let analyze change_info (file: file) fs =
Logs.debug "Generating the control flow graph.";
let (module CFG), skippedByEdge = compute_cfg_skips file in
let (module CFG), skippedByEdge = CfgTools.compute_cfg_skips file in
MyCFG.current_cfg := (module CFG);
analyze_loop (module CFG) file fs change_info skippedByEdge
21 changes: 1 addition & 20 deletions src/util/cilCfg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,7 @@
open GobConfig
open GoblintCil

class allBBVisitor = object (* puts every instruction into its own basic block *)
inherit nopCilVisitor
method! vstmt s =
match s.skind with
| Instr(il) ->
let list_of_stmts =
List.map (fun one_inst -> mkStmtOneInstr one_inst) il in
let block = mkBlock list_of_stmts in
ChangeDoChildrenPost(s, (fun _ -> s.skind <- Block(block); s))
| _ -> DoChildren

method! vvdec _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
end

let end_basic_blocks f =
let thisVisitor = new allBBVisitor in
visitCilFileSameGlobals thisVisitor f
include CilCfg0


class countLoopsVisitor(count) = object
Expand Down
33 changes: 33 additions & 0 deletions tests/regression/00-sanity/19-if-0.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
$ cfgDot 19-if-0.c

$ graph-easy --as=boxart main.dot
┌────────────────────────┐
│ main() │
└────────────────────────┘
│ (body)
┌────────────────────────┐ ┌────────────────────────┐
│ 19-if-0.c:15:9-15:27 │ Neg(0) │ 19-if-0.c:9:5-16:5 │
│ (19-if-0.c:15:9-15:27) │ ◀──────────────────── │ (19-if-0.c:9:9-9:10) │
└────────────────────────┘ └────────────────────────┘
│ │
│ │ Pos(0)
│ ▼
│ ┌────────────────────────┐
│ │ 19-if-0.c:11:9-11:16 │
│ │ (19-if-0.c:11:9-11:16) │
│ └────────────────────────┘
│ │
│ │ stuff()
│ ▼
│ ┌────────────────────────┐
│ __goblint_check(1) │ 19-if-0.c:17:5-17:13 │
└────────────────────────────────────────────▶ │ (unknown) │
└────────────────────────┘
│ return 0
┌────────────────────────┐
│ return of main() │
└────────────────────────┘
35 changes: 35 additions & 0 deletions tests/regression/00-sanity/20-if-0-realnode.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
$ cfgDot 20-if-0-realnode.c

$ graph-easy --as=boxart main.dot
┌─────────────────────────────────┐
│ main() │
└─────────────────────────────────┘
│ (body)
┌─────────────────────────────────┐
│ 20-if-0-realnode.c:8:5-14:5 │ Neg(0)
│ (20-if-0-realnode.c:8:9-8:10) │ ─────────┐
│ [20-if-0-realnode.c:7:5-8:5 │ │
│ (unknown)] │ ◀────────┘
└─────────────────────────────────┘
│ Pos(0)
┌─────────────────────────────────┐
│ 20-if-0-realnode.c:10:9-10:16 │
│ (20-if-0-realnode.c:10:9-10:16) │
└─────────────────────────────────┘
│ stuff()
┌─────────────────────────────────┐
│ 20-if-0-realnode.c:15:5-15:13 │
│ (unknown) │
└─────────────────────────────────┘
│ return 0
┌─────────────────────────────────┐
│ return of main() │
└─────────────────────────────────┘
Loading
Loading