|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 3 | +# SPDX-License-Identifier: Apache-2.0 OR MIT |
| 4 | + |
| 5 | +import argparse |
| 6 | + |
| 7 | +# Add flags related to debugging output. |
| 8 | +def add_loudness_flags(make_group, add_flag, config): |
| 9 | + group = make_group( |
| 10 | + "Loudness flags", "Determine how much textual output to produce.") |
| 11 | + add_flag(group, "--debug", action="store_true", |
| 12 | + help="Produce full debug information") |
| 13 | + add_flag(group, "--quiet", "-q", action="store_true", |
| 14 | + help="Produces no output, just an exit code and requested artifacts; overrides --verbose") |
| 15 | + add_flag(group, "--verbose", "-v", action="store_true", |
| 16 | + help="Output processing stages and commands, along with minor debug information") |
| 17 | + |
| 18 | +# Add flags which specify configurations for the proof. |
| 19 | +def add_linking_flags(make_group, add_flag, config): |
| 20 | + group = make_group("Linking flags", |
| 21 | + "Provide information about how to link the prover for RMC.") |
| 22 | + add_flag(group, "--c-lib", nargs="*", default=[], action="extend", |
| 23 | + help="Link external C files referenced by Rust code") |
| 24 | + add_flag(group, "--function", default="main", |
| 25 | + help="Entry point for verification") |
| 26 | + |
| 27 | +# Add flags that produce extra artifacts. |
| 28 | +def add_artifact_flags(make_group, add_flag, config): |
| 29 | + default_target = config["default-target"] |
| 30 | + assert default_target is not None, \ |
| 31 | + f"Missing item in parser config: \"default-target\".\n" \ |
| 32 | + "This is a bug; please report this to https://github.com/model-checking/rmc/issues." |
| 33 | + |
| 34 | + group = make_group( |
| 35 | + "Artifact flags", "Produce artifacts in addition to a basic RMC report.") |
| 36 | + add_flag(group, "--gen-c", action="store_true", |
| 37 | + help="Generate C file equivalent to inputted program") |
| 38 | + add_flag(group, "--gen-symbols", action="store_true", |
| 39 | + help="Generate a goto symbol table") |
| 40 | + add_flag(group, "--keep-temps", action="store_true", |
| 41 | + help="Keep temporary files generated throughout RMC process") |
| 42 | + add_flag(group, "--target-dir", default=default_target, metavar="DIR", |
| 43 | + help=f"Directory for all generated artifacts; defaults to \"{default_target}\"") |
| 44 | + |
| 45 | +# Add flags to turn off default checks. |
| 46 | +def add_check_flags(make_group, add_flag, config): |
| 47 | + group = make_group("Check flags", "Disable some or all default checks.") |
| 48 | + add_flag(group, "--no-default-checks", action="store_true", |
| 49 | + help="Disable all default checks") |
| 50 | + add_flag(group, "--no-memory-safety-checks", action="store_true", |
| 51 | + help="Disable default memory safety checks") |
| 52 | + add_flag(group, "--no-overflow-checks", action="store_true", |
| 53 | + help="Disable default overflow checks") |
| 54 | + add_flag(group, "--no-unwinding-checks", action="store_true", |
| 55 | + help="Disable default unwinding checks") |
| 56 | + |
| 57 | +# Add flags needed only for visualizer. |
| 58 | +def add_visualizer_flags(make_group, add_flag, config): |
| 59 | + group = make_group( |
| 60 | + "Visualizer flags", "Generate an HTML-based UI for the generated RMC report.\nSee https://github.com/awslabs/aws-viewer-for-cbmc.") |
| 61 | + add_flag(group, "--srcdir", default=".", |
| 62 | + help="The source directory: the root of the source tree") |
| 63 | + add_flag(group, "--visualize", action="store_true", |
| 64 | + help="Generate visualizer report to <target-dir>/report/html/index.html") |
| 65 | + add_flag(group, "--wkdir", default=".", |
| 66 | + help=""" |
| 67 | + The working directory: used to determine source locations in output; |
| 68 | + this is generally the location from which rmc is currently being invoked |
| 69 | + """) |
| 70 | + |
| 71 | +# Add flags for ad-hoc features. |
| 72 | +def add_other_flags(make_group, add_flag, config): |
| 73 | + group = make_group("Other flags") |
| 74 | + add_flag(group, "--allow-cbmc-verification-failure", action="store_true", |
| 75 | + help="Do not produce error return code on CBMC verification failure") |
| 76 | + add_flag(group, "--dry-run", action="store_true", |
| 77 | + help="Print commands instead of running them") |
| 78 | + |
| 79 | +# Add flags we don't expect end-users to use. |
| 80 | +def add_developer_flags(make_group, add_flag, config): |
| 81 | + group = make_group( |
| 82 | + "Developer flags", "These are generally meant for use by RMC developers, and are not stable.") |
| 83 | + add_flag(group, "--cbmc-args", nargs=argparse.REMAINDER, default=[], |
| 84 | + help="Pass through directly to CBMC; must be the last flag") |
| 85 | + add_flag(group, "--mangler", default="v0", choices=["v0", "legacy"], |
| 86 | + help="Change what mangler is used by the Rust compiler") |
| 87 | + |
| 88 | +# Adds the flags common to both rmc and cargo-rmc. |
| 89 | +# Allows you to specify flags/groups of flags to not add. |
| 90 | +# This does not return the parser, but mutates the one provided. |
| 91 | +def add_flags(parser, config, exclude_flags=[], exclude_groups=[]): |
| 92 | + # Keep track of what excluded flags and groups we've seen |
| 93 | + # so we can warn for possibly incorrect names passed in. |
| 94 | + excluded_flags = set() |
| 95 | + excluded_groups = set() |
| 96 | + |
| 97 | + # Add a group to the parser with title/description, and get a handler for it. |
| 98 | + def make_group(title=None, description=None): |
| 99 | + if title in exclude_groups: |
| 100 | + excluded_groups.add(group.title) |
| 101 | + return None |
| 102 | + |
| 103 | + return parser.add_argument_group(title, description) |
| 104 | + |
| 105 | + # Add the flag to the group, |
| 106 | + def add_flag(group, flag, *args, **kwargs): |
| 107 | + if group == None: |
| 108 | + return |
| 109 | + |
| 110 | + if flag in exclude_flags: |
| 111 | + excluded_flags.add(flag) |
| 112 | + return |
| 113 | + |
| 114 | + group.add_argument(flag, *args, **kwargs) |
| 115 | + |
| 116 | + add_groups = [ |
| 117 | + add_loudness_flags, |
| 118 | + add_linking_flags, |
| 119 | + add_artifact_flags, |
| 120 | + add_check_flags, |
| 121 | + add_visualizer_flags, |
| 122 | + add_other_flags, |
| 123 | + add_developer_flags |
| 124 | + ] |
| 125 | + |
| 126 | + for add_group in add_groups: |
| 127 | + add_group(make_group, add_flag, config) |
| 128 | + |
| 129 | + # Error if any excluded flags/groups don't exist. |
| 130 | + extra_flags = set(exclude_flags) - excluded_flags |
| 131 | + extra_groups = set(exclude_groups) - excluded_groups |
| 132 | + assert len(extra_flags.union(extra_groups)) == 0, \ |
| 133 | + f"Attempt to exclude parser options which don't exist: {extra_groups.union(extra_flags)}\n" \ |
| 134 | + "This is a bug; please report this to https://github.com/model-checking/rmc/issues." |
0 commit comments