0

I have code in a domain-specific language (DSL). Files in this language are translated into C source code files, which are then compiled into binaries by a usual compiler toolchain (GCC):

DSL file --> C file --> Object file --> binary file

I want to measure test coverage for code written in this DSL. The language lacks native tooling support for measuring test coverage. However, I can use traditional GCC tools such as gcov and compiler's --coverage flags (or Clang equivalents) to instrument the generated binaries. The intermediate C-representation can then be annotated with coverage information.

DSL file --> C file --> Instrumented object file --> instrumented binary file --> coverage database
                ↕                                                                     |
         annotated C file <-----------------------------------------------------------+

The problem is, the intermediate C-code does not precisely map to its DSL input: symbols may be renamed, methods moved around, lines added and removed etc.

It is quite hard to mentally map the source code lines back and forth.

Is there a way to trace back collected coverage information to associate it with the original DSL code?

1 Answer 1

0

It turns out that gcovr (and I assume gcov which it wraps does it as well) understands #line preprocessor directives. This directive informs that code lines following it should be treated as if they came from a differently named source file and were placed at different line number.

So as long as my DSL-to-C translator is capable to annotate the generated code with #lines as shown below, the coverage tools are capable of associating the coverage database with the original DSL code:

#line 3248 "foo-controller-dsl.c"
/* get_allowed_deadline */
static uint64 _dsl_M_get_allowed_deadline(foo_controller_t *_dev, obj_t *cpu)
#line 179 "/src/foo-controller/foo-controller.dsl"
{
    #line 180 "/src/foo-controller/foo-controller.dsl"
    uint64 v618_baz_freq  = _dsl_M_ctr_storage__get_ref_freq(_dev);
    #line 181 "/src/foo-controller/foo-controller.dsl"
    double v618_threshold_seconds  = _dsl_M_get_threshold_in_seconds(_dev, cpu);
    #line 182 "/src/foo-controller/foo-controller.dsl"
    double v618_threshold_baz_units  = v618_threshold_seconds * (double )v618_baz_freq;
    #line 184 "/src/foo-controller/foo-controller.dsl"
    double v618_baz_counter  = _dsl_M_ctr_storage__get_ctr(_dev);
    #line 185 "/src/foo-controller/foo-controller.dsl"
    double v618_allowed_deadline  = v618_baz_counter + v618_threshold_baz_units;
    #line 187 "/src/foo-controller/foo-controller.dsl"
    return (uint64 )((int64 )v618_allowed_deadline);
    #line 188 "/src/foo-controller/foo-controller.dsl"
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.