Chuanqi Xu 03921b979d
[serialization] No transitive type change (#92511)
Following of https://github.com/llvm/llvm-project/pull/92085. 

#### motivation

The motivation is still cutting of the unnecessary change in the
dependency chain. See the above link (recursively) for details.

And this will be the last patch of the `no-transitive-*-change` series.
If there are any following patches, they might be C++20 Named modules
specific to handle special grammars like `ADL` (See the reply in
https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755/53
for example). So they won't affect the whole serialization part as the
series patch did.

#### example

After this patch, finally we are able to cut of unnecessary change of
types. For example,

```

//--- m-partA.cppm
export module m:partA;

//--- m-partA.v1.cppm
export module m:partA;

namespace NS {
    class A {
        public:
            int getValue() {
                return 43;
            }
    };
}

//--- m-partB.cppm
export module m:partB;

export inline int getB() {
    return 430;
}

//--- m.cppm
export module m;
export import :partA;
export import :partB;

//--- useBOnly.cppm
export module useBOnly;
import m;

export inline int get() {
    return getB();
}
```

The BMI of `useBOnly.cppm` is expected to not change if we only add a
new class in `m:partA`. This will be pretty useful in practice.

#### implementation details

The key idea of this patch is similar with the previous patches: extend
the 32bits type ID to 64bits so that we can store the module file index
in the higher bits. Then the encoding of the type ID is independent on
the imported modules.

But there are two differences from the previous patches:
- TypeID is not completely an index of serialized types. We used the
lower 3 bits to store the qualifiers.
- TypeID won't take part in any lookup process. So the uses of TypeID is
much less than the previous patches.

The first difference make we have some more slightly complex bit
operations. And the second difference makes the patch much simpler than
the previous ones.
2024-06-21 09:21:40 +08:00

91 lines
3.4 KiB
C++

//===- ModuleFile.cpp - Module description --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the ModuleFile class, which describes a module that
// has been loaded from an AST file.
//
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ModuleFile.h"
#include "ASTReaderInternals.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace serialization;
using namespace reader;
ModuleFile::~ModuleFile() {
delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
}
template<typename Key, typename Offset, unsigned InitialCapacity>
static void
dumpLocalRemap(StringRef Name,
const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) {
if (Map.begin() == Map.end())
return;
using MapType = ContinuousRangeMap<Key, Offset, InitialCapacity>;
llvm::errs() << " " << Name << ":\n";
for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
I != IEnd; ++I) {
llvm::errs() << " " << I->first << " -> " << I->second << "\n";
}
}
LLVM_DUMP_METHOD void ModuleFile::dump() {
llvm::errs() << "\nModule: " << FileName << "\n";
if (!Imports.empty()) {
llvm::errs() << " Imports: ";
for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
if (I)
llvm::errs() << ", ";
llvm::errs() << Imports[I]->FileName;
}
llvm::errs() << "\n";
}
// Remapping tables.
llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset
<< '\n';
llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n'
<< " Number of identifiers: " << LocalNumIdentifiers << '\n';
llvm::errs() << " Base macro ID: " << BaseMacroID << '\n'
<< " Number of macros: " << LocalNumMacros << '\n';
dumpLocalRemap("Macro ID local -> global map", MacroRemap);
llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n'
<< " Number of submodules: " << LocalNumSubmodules << '\n';
dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap);
llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n'
<< " Number of selectors: " << LocalNumSelectors << '\n';
dumpLocalRemap("Selector ID local -> global map", SelectorRemap);
llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID
<< '\n'
<< " Number of preprocessed entities: "
<< NumPreprocessedEntities << '\n';
dumpLocalRemap("Preprocessed entity ID local -> global map",
PreprocessedEntityRemap);
llvm::errs() << " Base type index: " << BaseTypeIndex << '\n'
<< " Number of types: " << LocalNumTypes << '\n';
llvm::errs() << " Base decl index: " << BaseDeclIndex << '\n'
<< " Number of decls: " << LocalNumDecls << '\n';
}