RFR: 7903602: Simplify handling of structs/unions
Maurizio Cimadamore
mcimadamore at openjdk.org
Wed Dec 6 14:56:14 UTC 2023
This PR simplifies how declarations and layouts for C structs/unions are created, by splitting the monolithic `RecordLayoutComputer` into two passes:
1. As part of parsing (in `TreeMaker`) a scoped declaration is created for a struct, which contains all the relevant fields. This declaration is annotated with a bunch of attributes which reify some of the properties of the underlying clang cursors/types (such as sizes, alignments and offsets).
2. We now have a new static method in `Declaration`, namely `Declaration::layoutFor` which allows clients to obtain the layout for a given declaration. For most declaration, this method will get the type and then call `Type::layoutFor`. But for scoped declarations we will compute a new struct/union layout.
3. The already computed layouts are attached to the scoped declaration using an attribute, so that we avoid computing things multiple times.
I actually started off with a declaration visitor which attached layouts to all scoped declarations, but then reverted to a more lazy approach like the one described in (2) because this approach is more amenable for tests dynamically querying layouts of parsed declarations (whereas if layouts depended on a certain visitor being run after parsing, all such tests could not be supported).
Note that the logic which computes a struct/union layout is designed so that it always yields the same answer. That is, even if a client asks the layout for a nested anon struct first, the layout is computed correctly. This is possible because I've removed a lot of stateful logic from the computation, namely:
* the name of anonymous nested declaration is uniquely derived from the declaration position
* the starting offset used for layout computation is derived from the offset of the first member of the scoped declaration (if we're seeing an anonymous struct, otherwise the starting offset is just zero)
An interesting consequence of this PR is that now the Declaration/Type API become layout-agnostic: while it's possible to compute a layout/function descriptor from a declaration or type, the declaration/type IRs do not embed any layout information. This change is also evident in the treatment for primitive types, which no longer have a pre-determined associated layout. That is, jextract declaration are now pure wrappers around clang cursors, and nothing more. Of course given the information in a declaration we can derive a layout, but that's an orthogonal operation: a declaration exists even w/o a layout.
Finally, I've cleaned up some scoped kinds (class, namespace) - and corresponding factories - which were not really used.
-------------
Commit messages:
- Drop class enum from Scoped.Kind
- Add comments on new attributes
- Revert macro parser changes
- Make Declaration::layoutFor order-independent
- Simplify DeclarationImpl::layoutFor
- Simplify primitive typedef builder logic
- More code cleanup
- Revert spurious test changes
- Simplify code
- All tests pass
- ... and 3 more: https://git.openjdk.org/jextract/compare/d97ee208...1dc1b6a1
Changes: https://git.openjdk.org/jextract/pull/154/files
Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=154&range=00
Issue: https://bugs.openjdk.org/browse/CODETOOLS-7903602
Stats: 1149 lines in 17 files changed: 342 ins; 723 del; 84 mod
Patch: https://git.openjdk.org/jextract/pull/154.diff
Fetch: git fetch https://git.openjdk.org/jextract.git pull/154/head:pull/154
PR: https://git.openjdk.org/jextract/pull/154
More information about the jextract-dev
mailing list