Definition
A Code Fragment in RVVTS is defined as an indivisible sequence of at least one assembler instruction implementing an operation [1]. It is the atomic unit used to organize and handle assembler code inside the framework.
Examples drawn from the RISC-V Vector (RVV) extension include:
- A Code Fragment for an RVV
addoperation, which contains a single vector add assembler instruction. - A Code Fragment for an RVV bounded load/store operation, which contains multiple assembler instructions to realize the bounding together with a vector load/store instruction [1].
Role within RVVTS
Code Fragments are the building blocks of a Code Block, which is a sequence of Code Fragments that together form an entity executable on a RISC-V machine by RVVTS [1]. The data structure for a Code Block provides methods to:
- Modify the contained code,
- Retrieve sub-blocks,
- Save/load Code Blocks to/from files.
Code Blocks can be created manually, loaded from files, or generated automatically by the ISG or through Code Minimization [1].
Generation by the Grammar-based ISG
RVVTS includes a grammar-based Instruction Sequence Generator (ISG) that supports RV32 and RV64 RISC-V configurations, the base integer (I) extension, and the RVV extension (with partial floating-point support for F/D where required for RVV) [1]. The ISG:
- Uses a context-free grammar consisting of non-terminal and terminal symbols.
- Randomly selects expansion candidates for non-terminal symbols until only terminal symbols remain.
- Returns the result as a Code Fragment [1].
To handle cases beyond the expressiveness of pure context-free grammars (e.g., dynamically parameterized bounded values or bounded load/store sequences composed of multiple dependent instructions), the grammar is extended with special function symbols bound to Python functions [2]. These functions are invoked by the ISG to provide context-sensitive values that are integrated into the generated Code Fragment, for example:
- Generating immediate values,
- Performing register allocations,
- Producing valid values for CSRs,
- Generating bounded load/stores [2].
Manipulation during Delta Code Reduction
In the Delta Code Reduction stage, a failing Code Block is minimized using a binary-search technique that tracks the last good and bad code positions and a current test position [3]. Each iteration executes a sub-part of the Code Block (positions 0 to the test position) using a CodeCompareRunner; code positions are updated and the search area is halved. The algorithm stops once it has identified the earliest single bad Code Fragment, located at the bad position [3].
The result of Delta Code Reduction is a reduced Code Block consisting of a number of non-failing Code Fragments followed by a single failing Code Fragment at the end. In many cases, this already isolates a single failing instruction (the last Code Fragment) [3].
Manipulation during Extension and Reduction Phases
Within the CodeErrMinRunner workflow, two phases operate on Code Fragments to densify a Code Block without hurting coverage [3]:
- Extension phase: At each iteration, the ISG generates a new Code Fragment, which is inserted at a random position in a copy of the current Code Block. The new Code Block is instrumented, compiled, and executed by a
CodeCheckRunner, which returns a Machine State and a coverage value. The new Code Block is accepted only if (i) the Machine State is valid and (ii) the coverage is maintained or improved compared to the original Code Block [3]. - Reduction phase: At each iteration, a random Code Fragment is removed from a copy of the current Code Block. The new Code Block is executed via a
CodeCheckRunner, and the same validity and coverage requirements are checked [3].
The Runner switches between these phases based on a configurable number of iterations per phase and can be stopped at any time by the instantiating program (e.g., after a given number of iterations, time limit, or coverage threshold) [3].
Related Concepts in the Wider Literature
The term code fragment also appears in adjacent areas of software engineering research, although with different scopes:
- In static-analysis validation research, a code fragment refers to syntactically valid, semantic-preserving executable snippets generated from static warnings and exercised by build/test systems such as fuzzers, KLEE, and Valgrind (arXiv:2106.04735v3).
- In code-clone investigation research, code fragments of detected clones are treated as sequences of words for topic-based clustering and tagging (arXiv:2110.01092v1).
These usages share the general notion of a small, self-contained piece of code but are not part of the RVVTS-specific definition above.