Skip to content

Commit e6ecff8

Browse files
committed
[C++20] [Modules] Add Release Notes and Documents for Reduced BMI
See https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755, #75894 and #85050 for the background.
1 parent c81e5fa commit e6ecff8

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ New Compiler Flags
214214
This diagnostic can be disabled to make ``-Wmissing-field-initializers`` behave
215215
like it did before Clang 18.x. Fixes #GH56628
216216

217+
- ``-fexperimental-modules-reduced-bmi`` enables the Reduced BMI for C++20 named modules.
218+
See the document of standard C++ modules for details.
219+
217220
Deprecated Compiler Flags
218221
-------------------------
219222

clang/docs/StandardCPlusPlusModules.rst

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,112 @@ is attached to the global module fragments. For example:
520520

521521
Now the linkage name of ``NS::foo()`` will be ``_ZN2NS3fooEv``.
522522

523+
Reduced BMI
524+
-----------
525+
526+
To support the 2 phase compilation model, Clang chose to put everything needed to
527+
produce an object into the BMI. But every consumer of the BMI, except itself, doesn't
528+
need such informations. It makes the BMI to larger and so may introduce unnecessary
529+
dependencies into the BMI. To mitigate the problem, we decided to reduce the information
530+
contained in the BMI.
531+
532+
To be clear, we call the default BMI as Full BMI and the new introduced BMI as Reduced
533+
BMI.
534+
535+
Users can use ``-fexperimental-modules-reduced-bmi`` flag to enable the Reduced BMI.
536+
537+
For one phase compilation model (CMake implements this model), with
538+
``-fexperimental-modules-reduced-bmi``, the generated BMI will be Reduced BMI automatically.
539+
(The output path of the BMI is specified by ``-fmodule-output=`` as usual one phase
540+
compilation model).
541+
542+
It is still possible to support Reduced BMI in two phase compilation model. With
543+
``-fexperimental-modules-reduced-bmi``, ``--precompile`` and ``-fmodule-output=`` specified,
544+
the generated BMI specified by ``-o`` will be full BMI and the BMI specified by
545+
``-fmodule-output=`` will be Reduced BMI. The dependency graph may be:
546+
547+
.. code-block:: none
548+
549+
module-unit.cppm --> module-unit.full.pcm -> module-unit.o
550+
|
551+
-> module-unit.reduced.pcm -> consumer1.cpp
552+
-> consumer2.cpp
553+
-> ...
554+
-> consumer_n.cpp
555+
556+
We don't emit diagnostics if ``-fexperimental-modules-reduced-bmi`` is used with a non-module
557+
unit. This design helps the end users of one phase compilation model to perform experiments
558+
early without asking for the help of build systems. The users of build systems which supports
559+
two phase compilation model still need helps from build systems.
560+
561+
Within Reduced BMI, we won't write unreachable entities from GMF, definitions of non-inline
562+
functions and non-inline variables. This may not be a transparent change.
563+
`[module.global.frag]ex2 <https://eel.is/c++draft/module.global.frag#example-2>`_ may be a good
564+
example:
565+
566+
.. code-block:: c++
567+
568+
// foo.h
569+
namespace N {
570+
struct X {};
571+
int d();
572+
int e();
573+
inline int f(X, int = d()) { return e(); }
574+
int g(X);
575+
int h(X);
576+
}
577+
578+
// M.cppm
579+
module;
580+
#include "foo.h"
581+
export module M;
582+
template<typename T> int use_f() {
583+
N::X x; // N::X, N, and :: are decl-reachable from use_f
584+
return f(x, 123); // N::f is decl-reachable from use_f,
585+
// N::e is indirectly decl-reachable from use_f
586+
// because it is decl-reachable from N::f, and
587+
// N::d is decl-reachable from use_f
588+
// because it is decl-reachable from N::f
589+
// even though it is not used in this call
590+
}
591+
template<typename T> int use_g() {
592+
N::X x; // N::X, N, and :: are decl-reachable from use_g
593+
return g((T(), x)); // N::g is not decl-reachable from use_g
594+
}
595+
template<typename T> int use_h() {
596+
N::X x; // N::X, N, and :: are decl-reachable from use_h
597+
return h((T(), x)); // N::h is not decl-reachable from use_h, but
598+
// N::h is decl-reachable from use_h<int>
599+
}
600+
int k = use_h<int>();
601+
// use_h<int> is decl-reachable from k, so
602+
// N::h is decl-reachable from k
603+
604+
// M-impl.cpp
605+
module M;
606+
int a = use_f<int>(); // OK
607+
int b = use_g<int>(); // error: no viable function for call to g;
608+
// g is not decl-reachable from purview of
609+
// module M's interface, so is discarded
610+
int c = use_h<int>(); // OK
611+
612+
In the above example, the function definition of ``N::g`` is elided from the Reduced
613+
BMI of ``M.cppm``. Then the use of ``use_g<int>`` in ``M-impl.cpp`` fails
614+
to instantiate. For such issues, users can add references to ``N::g`` in the module purview
615+
of ``M.cppm`` to make sure it is reachable, e.g., ``using N::g;``.
616+
617+
We think the Reduced BMI is the correct direction. But given it is a drastic change,
618+
we'd like to make it experimental first to avoid breaking existing users. The roadmap
619+
of Reduced BMI may be:
620+
621+
1. ``-fexperimental-modules-reduced-bmi`` is opt in for 1~2 releases. The period depends
622+
on testing feedbacks.
623+
2. We would announce Reduced BMI is not experimental and introduce ``-fmodules-reduced-bmi``.
624+
and suggest users to enable this mode. This may takes 1~2 releases too.
625+
3. Finally we will enable this by default. When that time comes, the term BMI will refer to
626+
the reduced BMI today and the Full BMI will only be meaningful to build systems which
627+
loves to support two phase compilations.
628+
523629
Performance Tips
524630
----------------
525631

0 commit comments

Comments
 (0)