add "Improving Translate-C" section to CONTRIBUTING.md

This commit is contained in:
Andrew Kelley 2020-01-05 15:42:55 -05:00
parent d7bff05098
commit 62bebda270
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9

View File

@ -123,3 +123,61 @@ When developing on Linux, another option is available to you: `-Denable-wine`.
This will enable running behavior tests and std lib tests with Wine. It's
recommended for Linux users to install Wine and enable this testing option
when editing the standard library or anything Windows-related.
#### Improving Translate-C
Please read the [Editing Source Code](#editing-source-code) section as a
prerequisite to this one.
`translate-c` is a feature provided by Zig that converts C source code into
Zig source code. It powers the `zig translate-c` command as well as
[@cImport](https://ziglang.org/documentation/master/#cImport), allowing Zig
code to not only take advantage of function prototypes defined in .h files,
but also `static inline` functions written in C, and even some macros.
This feature works by using libclang API to parse and semantically analyze
C/C++ files, and then based on the provided AST and type information,
generating Zig AST, and finally using the mechanisms of `zig fmt` to render
the Zig AST to a file.
The relevant tests for this feature are:
* `test/run_translated_c.zig` - each test case is C code with a `main` function. The C code
is translated into Zig code, compiled, and run, and tests that the expected output is the
same, and that the program exits cleanly. This kind of test coverage is preferred, when
possible, because it makes sure that the resulting Zig code is actually viable.
* `test/translate_c.zig` - each test case is C code, with a list of expected strings which
must be found in the resulting Zig code. This kind of test is more precise in what it
measures, but does not provide test coverage of whether the resulting Zig code is valid.
This feature is self-hosted, even though Zig is not fully self-hosted yet. In the Zig source
repo, we maintain a C API on top of Clang's C++ API:
* `src/zig_clang.h` - the C API that we maintain on top of Clang's C++ API. This
file does not include any Clang's C++ headers. Instead, C types and C enums are defined
here.
* `src/zig_clang.cpp` - a lightweight wrapper that fulfills the C API on top of the
C++ API. It takes advantage of `static_assert` to make sure we get compile errors when
Clang's C++ API changes. This one file necessarily does include Clang's C++ headers, which
makes it the slowest-to-compile source file in all of Zig's codebase.
* `src-self-hosted/clang.zig` - the Zig equivalent of `src/zig_clang.h`. This is a manually
maintained list of types and functions that are ABI-compatible with the Clang C API we
maintain. In theory this could be generated by running translate-c on `src/zig_clang.h`,
but that would introduce a dependency cycle, since we are using this file to implement
translate-c.
Finally, the actual source code for the translate-c feature is
`src-self-hosted/translate_c.zig`. This code uses the Clang C API exposed by
`src-self-hosted/clang.zig`, and produces Zig AST.
The steps for contributing to translate-c look like this:
1. Identify a test case you want to improve. Add it as a run-translated-c test
case (usually preferable), or as a translate-c test case.
2. Edit `src-self-hosted/translate_c.zig` to improve the behavior.
3. Run the relevant tests: `./zig build test-run-translated-c test-translate-c`