Hello everyone,
it's time to share something I've tinkering with for a few days.

First, motivation:
There's a couple of identifiers in libc (both types and constants),
that are special in ways that make organization difficult. On one
side, we have things like size_t and NULL that are supposed to be
defined in a multitude of different headers, not having a single
"home". On the other side, we have lots of different integer types and
property macros that are split across several headers, but are much
more naturally defined all together in one place.

In current HelenOS, some of the types and constants are defined by an
autogenerated header (itself broken in several ways), which is then
symlinked to several different locations; some are defined by
copypasta in libarch (there's just two versions, 32b vs 64b, but
there's a copy of those definitions for each architecture, and further
duplication between uspace and kernel); the rest are sprinkled
wherever was the most convenient at the time (I'm looking at you,
ptrdiff_t).


Some libraries, e.g. musl, sort this out by having a single big header
that's included after defining macros like "__need_size_t",
"__need_NULL", etc, and itself does more magic with "XXX_is_defined"
macros. This is an antipattern, it makes the headers non-modular, and
breaks clang's -fmodules feature. Clang modules are not the focus of
this writeup, but as an appetizer, I will point out that properly
modular headers could give us bonuses like diagnostics for unnecessary
includes.


Instead, I propose the following:

In the abi/include directory, shared between kernel and uspace, there
shall be a directory of "building block" headers (in my current
implementation, this directory is named "_bits", but this is subject
to bikeshedding). These headers are private and are only supposed to
be included by other headers that expose the API. Each of these
building blocks defines a particular subset of the basic types, at
arbitrary granularity. E.g. there may be <_bits/size_t.h> that defines
just size_t, and <_bits/stdint.h> that defines some or all of
<stdint.h> types.

However, the building block headers don't contain the actual
definition of those types and constants, they simply refer to
preestablished macros with reserved names, such as __SIZE_TYPE__.
These macros are established all in one place, in <_bits/macros.h>,
which is where all the real magic happens. macros.h expects a small
subset of predefined macros (which are deliberately picked to be a
subset of predefined macros provided by both GCC and clang, but can
also independently be provided by autotool.py), and derives all the
rest of the information necessary to provide a complete,
self-consistent library.

You can check out the current version here:
https://github.com/le-jzr/helenos/tree/types2/abi/include/_bits


Thoughts? Ideas? Fearsome criticism?

-- jzr

_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/listinfo/helenos-devel

Reply via email to