aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/ASTUnit.cpp
AgeCommit message (Collapse)AuthorFilesLines
12 days[clang] Pass VFS into `ASTUnit::LoadFromASTFile()` (#159166)Jan Svoboda1-2/+3
This PR makes the `VFS` parameter to `ASTUnit::LoadFromASTFile()` required and explicit, rather than silently defaulting to the real file system. This makes it easy to correctly propagate the fully-configured VFS and load any input files like the rest of the compiler does.
14 days[clang] Initialize the file system explicitly (#158381)Jan Svoboda1-3/+5
This PR is a part of the effort to make the VFS used in the compiler more explicit and consistent. Instead of creating the VFS deep within the compiler (in `CompilerInstance::createFileManager()`), clients are now required to explicitly call `CompilerInstance::createVirtualFileSystem()` and provide the base VFS from the outside. This PR also helps in breaking up the dependency cycle where creating a properly configured `DiagnosticsEngine` requires a properly configured VFS, but creating properly configuring a VFS requires the `DiagnosticsEngine`. Both `CompilerInstance::create{FileManager,Diagnostics}()` now just use the VFS already in `CompilerInstance` instead of taking one as a parameter, making the VFS consistent across the instance sub-object.
2025-08-27[clang] NFC: reintroduce clang/include/clang/AST/Type.h (#155050)Matheus Izvekov1-1/+1
This reintroduces `Type.h`, having earlier been renamed to `TypeBase.h`, as a redirection to `TypeBase.h`, and redirects most users to include the former instead. This is a preparatory patch for being able to provide inline definitions for `Type` methods which would otherwise cause a circular dependency with `Decl{,CXX}.h`. Doing these operations into their own NFC patch helps the git rename detection logic work, preserving the history. This patch makes clang just a little slower to build (~0.17%), just because it makes more code indirectly include `DeclCXX.h`.
2025-08-27[clang] NFC: rename clang/include/clang/AST/Type.h to TypeBase.h (#155049)Matheus Izvekov1-1/+1
This is a preparatory patch, to be able to provide inline definitions for `Type` functions which depend on `Decl{,CXX}.h`. As the latter also depends on `Type.h`, this would not be possible without some reorganizing. Splitting this rename into its own patch allows git to track this as a rename, and preserve all git history, and not force any code reformatting. A later NFC patch will reintroduce `Type.h` as redirection to `TypeBase.h`, rewriting most places back to directly including `Type.h` instead of `TypeBase.h`, leaving only a handful of places where this is necessary. Then yet a later patch will exploit this by making more stuff inline.
2025-08-09[clang] Improve nested name specifier AST representation (#147835)Matheus Izvekov1-1/+1
This is a major change on how we represent nested name qualifications in the AST. * The nested name specifier itself and how it's stored is changed. The prefixes for types are handled within the type hierarchy, which makes canonicalization for them super cheap, no memory allocation required. Also translating a type into nested name specifier form becomes a no-op. An identifier is stored as a DependentNameType. The nested name specifier gains a lightweight handle class, to be used instead of passing around pointers, which is similar to what is implemented for TemplateName. There is still one free bit available, and this handle can be used within a PointerUnion and PointerIntPair, which should keep bit-packing aficionados happy. * The ElaboratedType node is removed, all type nodes in which it could previously apply to can now store the elaborated keyword and name qualifier, tail allocating when present. * TagTypes can now point to the exact declaration found when producing these, as opposed to the previous situation of there only existing one TagType per entity. This increases the amount of type sugar retained, and can have several applications, for example in tracking module ownership, and other tools which care about source file origins, such as IWYU. These TagTypes are lazily allocated, in order to limit the increase in AST size. This patch offers a great performance benefit. It greatly improves compilation time for [stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for `test_on2.cpp` in that project, which is the slowest compiling test, this patch improves `-c` compilation time by about 7.2%, with the `-fsyntax-only` improvement being at ~12%. This has great results on compile-time-tracker as well: ![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831) This patch also further enables other optimziations in the future, and will reduce the performance impact of template specialization resugaring when that lands. It has some other miscelaneous drive-by fixes. About the review: Yes the patch is huge, sorry about that. Part of the reason is that I started by the nested name specifier part, before the ElaboratedType part, but that had a huge performance downside, as ElaboratedType is a big performance hog. I didn't have the steam to go back and change the patch after the fact. There is also a lot of internal API changes, and it made sense to remove ElaboratedType in one go, versus removing it from one type at a time, as that would present much more churn to the users. Also, the nested name specifier having a different API avoids missing changes related to how prefixes work now, which could make existing code compile but not work. How to review: The important changes are all in `clang/include/clang/AST` and `clang/lib/AST`, with also important changes in `clang/lib/Sema/TreeTransform.h`. The rest and bulk of the changes are mostly consequences of the changes in API. PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just for easier to rebasing. I plan to rename it back after this lands. Fixes #136624 Fixes https://github.com/llvm/llvm-project/issues/43179 Fixes https://github.com/llvm/llvm-project/issues/68670 Fixes https://github.com/llvm/llvm-project/issues/92757
2025-08-01NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (#151782)James Y Knight1-36/+41
This commit handles the following types: - clang::ExternalASTSource - clang::TargetInfo - clang::ASTContext - clang::SourceManager - clang::FileManager Part of cleanup #151026
2025-07-31NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (#151545)James Y Knight1-7/+8
Handles clang::DiagnosticsEngine and clang::DiagnosticIDs. For DiagnosticIDs, this mostly migrates from `new DiagnosticIDs` to convenience method `DiagnosticIDs::create()`. Part of cleanup https://github.com/llvm/llvm-project/issues/151026
2025-07-31NFC: Clean up construction of IntrusiveRefCntPtr from raw pointers for ↵James Y Knight1-4/+5
llvm::vfs::FileSystem. (#151407) This switches to `makeIntrusiveRefCnt<FileSystem>` where creating a new object, and to passing/returning by `IntrusiveRefCntPtr<FileSystem>` instead of `FileSystem*` or `FileSystem&`, when dealing with existing objects. Part of cleanup #151026.
2025-07-15[clang][modules] Serialize `CodeGenOptions` (#146422)Jan Svoboda1-12/+24
Some `LangOptions` duplicate their `CodeGenOptions` counterparts. My understanding is that this was done solely because some infrastructure (like preprocessor initialization, serialization, module compatibility checks, etc.) were only possible/convenient for `LangOptions`. This PR implements the missing support for `CodeGenOptions`, which makes it possible to remove some duplicate `LangOptions` fields and simplify the logic. Motivated by https://github.com/llvm/llvm-project/pull/146342.
2025-07-09[Clang] Respect MS layout attributes during CUDA/HIP device compilation ↵Yaxun (Sam) Liu1-1/+1
(#146620) This patch fixes an issue where Microsoft-specific layout attributes, such as __declspec(empty_bases), were ignored during CUDA/HIP device compilation on a Windows host. This caused a critical memory layout mismatch between host and device objects, breaking libraries that rely on these attributes for ABI compatibility. The fix introduces a centralized hasMicrosoftRecordLayout() check within the TargetInfo class. This check is aware of the auxiliary (host) target and is set during TargetInfo::adjust if the host uses a Microsoft ABI. The empty_bases, layout_version, and msvc::no_unique_address attributes now use this centralized flag, ensuring device code respects them and maintains layout consistency with the host. Fixes: https://github.com/llvm/llvm-project/issues/146047
2025-07-07NFC, use structured binding to simplify the code.Haojian Wu1-3/+1
2025-05-31[Frontend] Remove unused includes (NFC) (#142256)Kazu Hirata1-4/+0
These are identified by misc-include-cleaner. I've filtered out those that break builds. Also, I'm staying away from llvm-config.h, config.h, and Compiler.h, which likely cause platform- or compiler-specific build failures.
2025-05-22Reapply "[clang] Remove intrusive reference count from `DiagnosticOptions` ↵Jan Svoboda1-2/+12
(#139584)" This reverts commit e2a885537f11f8d9ced1c80c2c90069ab5adeb1d. Build failures were fixed right away and reverting the original commit without the fixes breaks the build again.
2025-05-22Revert "[clang] Remove intrusive reference count from `DiagnosticOptions` ↵Kazu Hirata1-12/+2
(#139584)" This reverts commit 9e306ad4600c4d3392c194a8be88919ee758425c. Multiple builtbot failures have been reported: https://github.com/llvm/llvm-project/pull/139584
2025-05-22[clang] Remove intrusive reference count from `DiagnosticOptions` (#139584)Jan Svoboda1-2/+12
The `DiagnosticOptions` class is currently intrusively reference-counted, which makes reasoning about its lifetime very difficult in some cases. For example, `CompilerInvocation` owns the `DiagnosticOptions` instance (wrapped in `llvm::IntrusiveRefCntPtr`) and only exposes an accessor returning `DiagnosticOptions &`. One would think this gives `CompilerInvocation` exclusive ownership of the object, but that's not the case: ```c++ void shareOwnership(CompilerInvocation &CI) { llvm::IntrusiveRefCntPtr<DiagnosticOptions> CoOwner = &CI.getDiagnosticOptions(); // ... } ``` This is a perfectly valid pattern that is being actually used in the codebase. I would like to ensure the ownership of `DiagnosticOptions` by `CompilerInvocation` is guaranteed to be exclusive. This can be leveraged for a copy-on-write optimization later on. This PR changes usages of `DiagnosticOptions` across `clang`, `clang-tools-extra` and `lldb` to not be intrusively reference-counted.
2025-05-19Revert "[clang][modules] Timestamp-less validation API (#139987)"Jan Svoboda1-8/+4
This reverts commit 7a242387c950c7060143da6da0e6fb91f36bb458. Even after 175f8a44, the Modules/fmodules-validate-once-per-build-session.c test is not fixed on the clang-armv8-quick build bot. (Failure occurs on line 114.)
2025-05-19Reland "[clang][modules] Timestamp-less validation API (#139987)"Jan Svoboda1-4/+8
This reverts commit 18b885f66babff3a10451bc811ffc077d61ed8ee, effectively reapplying #139987. This commit fixes unit tests (for example ASTUnitTest.SaveLoadPreservesLangOptionsInPrintingPolicy) where the `ASTUnit::ModCache` pointer dereferenced within `ASTUnit::serialize()` was null. This commit makes sure each factory function does initialize `ASTUnit::ModCache`.
2025-05-14Revert "[clang][modules] Timestamp-less validation API" (#139987)Qinkun Bao1-6/+4
Reverts llvm/llvm-project#138983
2025-05-14[clang][modules] Timestamp-less validation API (#138983)Jan Svoboda1-4/+6
Timestamps are an implementation detail of the cross-process module cache implementation. This PR hides it from the `ModuleCache` API, which simplifies the in-process implementation.
2025-05-10[clang] Remove redundant calls to std::unique_ptr<T>::get (NFC) (#139399)Kazu Hirata1-3/+3
2025-05-01[clang][frontend] Require invocation to construct `CompilerInstance` (#137668)Jan Svoboda1-12/+7
This PR makes it so that `CompilerInvocation` needs to be provided to `CompilerInstance` on construction. There are a couple of benefits in my view: * Making it impossible to mis-use some `CompilerInstance` APIs. For example there are cases, where `createDiagnostics()` was called before `setInvocation()`, causing the `DiagnosticEngine` to use the default-constructed `DiagnosticOptions` instead of the intended ones. * This shrinks `CompilerInstance`'s state space. * This makes it possible to access **the** invocation in `CompilerInstance`'s constructor (to be used in a follow-up).
2025-04-29[clang] Hide the `LangOptions` pointer from `CompilerInvocation` (#137675)Jan Svoboda1-4/+6
This PR makes `CompilerInvocation` the sole owner of the `LangOptions` instance.
2025-04-28[clang] Hide the `TargetOptions` pointer from `CompilerInvocation` (#106271)Jan Svoboda1-1/+5
This PR hides the reference-counted pointer that holds `TargetOptions` from the public API of `CompilerInvocation`. This gives `CompilerInvocation` an exclusive control over the lifetime of this member, which will eventually be leveraged to implement a copy-on-write behavior. There are two clients that currently share ownership of that pointer: * `TargetInfo` - This was refactored to hold a non-owning reference to `TargetOptions`. The options object is typically owned by the `CompilerInvocation` or by the new `CompilerInstance::AuxTargetOpts` for the auxiliary target. This needed a bit of care in `ASTUnit::Parse()` to keep the `CompilerInvocation` alive. * `clangd::PreambleData` - This was refactored to exclusively own the `TargetOptions` that get moved out of the `CompilerInvocation`.
2025-04-25[clang] Do not share ownership of `HeaderSearchOptions` (#132984)Jan Svoboda1-3/+2
This PR makes it so that `CompilerInvocation` is the sole owner of the `HeaderSearchOptions` instance.
2025-04-04[clang] Do not share ownership of `PreprocessorOptions` (#133467)Jan Svoboda1-1/+1
This PR makes it so that `CompilerInvocation` is the sole owner of the `PreprocessorOptions` instance.
2025-03-25[clang][lex] Store non-owning options ref in `HeaderSearch` (#132780)Jan Svoboda1-2/+2
This makes it so that `CompilerInvocation` can be the only entity that manages ownership of `HeaderSearchOptions`, making it possible to implement copy-on-write semantics.
2025-03-14[clang][modules] Introduce new `ModuleCache` interface (#131193)Jan Svoboda1-11/+10
This PR adds new `ModuleCache` interface to Clang's implicitly-built modules machinery. The main motivation for this change is to create a second implementation that uses a more efficient kind of `llvm::AdvisoryLock` during dependency scanning. In addition to the lock abstraction, the `ModuleCache` interface also manages the existing `InMemoryModuleCache` instance. I found that compared to keeping these separate/independent, the code is a bit simpler now, since these are two tightly coupled concepts. I can envision a more efficient implementation of the `InMemoryModuleCache` for the single-process case too, which will be much easier to implement with the current setup. This is not intended to be a functional change.
2024-11-13Reapply "[clang] Introduce diagnostics suppression mappings (#112517)"Kadir Cetinkaya1-6/+11
This reverts commit 5f140ba54794fe6ca379362b133eb27780e363d7.
2024-11-12Revert "[clang] Introduce diagnostics suppression mappings (#112517)"Kadir Cetinkaya1-11/+6
This reverts commit 12e3ed8de8c6063b15916b3faf67c8c9cd17df1f. This reverts commit 41e3919ded78d8870f7c95e9181c7f7e29aa3cc4. There are some buildbot breakages in https://lab.llvm.org/buildbot/#/builders/18/builds/6832.
2024-11-12[clang] Introduce diagnostics suppression mappings (#112517)kadir çetinkaya1-6/+11
This implements https://discourse.llvm.org/t/rfc-add-support-for-controlling-diagnostics-severities-at-file-level-granularity-through-command-line/81292. Users now can suppress warnings for certain headers by providing a mapping with globs, a sample file looks like: ``` [unused] src:* src:*clang/*=emit ``` This will suppress warnings from `-Wunused` group in all files that aren't under `clang/` directory. This mapping file can be passed to clang via `--warning-suppression-mappings=foo.txt`. At a high level, mapping file is stored in DiagnosticOptions and then processed with rest of the warning flags when creating a DiagnosticsEngine. This is a functor that uses SpecialCaseLists underneath to match against globs coming from the mappings file. This implies processing warning options now performs IO, relevant interfaces are updated to take in a VFS, falling back to RealFileSystem when one is not available.
2024-11-11[clang][serialization] Enable `ASTWriter` to work with `Preprocessor` only ↵Jan Svoboda1-1/+1
(#115237) This PR builds on top of https://github.com/llvm/llvm-project/pull/115235 and makes it possible to call `ASTWriter::WriteAST()` with `Preprocessor` only instead of full `Sema` object. So far, there are no clients that leverage the new capability - that will come in a follow-up commit.
2024-10-28Remove support for RenderScript (#112916)Aaron Ballman1-2/+0
See https://discourse.llvm.org/t/rfc-deprecate-and-eventually-remove-renderscript-support/81284 for the RFC
2024-09-25[clang] Make deprecations of some `FileManager` APIs formal (#110014)Jan Svoboda1-1/+1
Some `FileManager` APIs still return `{File,Directory}Entry` instead of the preferred `{File,Directory}EntryRef`. These are documented to be deprecated, but don't have the attribute that warns on their usage. This PR marks them as such with `LLVM_DEPRECATED()` and replaces their usage with the recommended counterparts. NFCI.
2024-09-23[Frontend] Teach LoadFromASTFile to take FileName by StringRef (NFC) (#109583)Kazu Hirata1-1/+1
Without this patch, several callers of LoadFromASTFile construct an instance of std::string to be passed as FileName, only to be converted back to StringRef when LoadFromASTFile calls ReadAST. This patch changes the type of FileName to StringRef and updates the callers.
2024-08-08[re-format][Modules] Follow-up formatting to "Mention which AST file's ↵Volodymyr Sapsai1-4/+6
options differ from the current TU options." (#102484) Fix formatting for fdf8e3e31103bc81917cdb27150877f524bb2669.
2024-08-08[Modules][Diagnostic] Mention which AST file's options differ from the ↵Volodymyr Sapsai1-2/+4
current TU options. (#101413) Claiming a mismatch is always in a precompiled header is wrong and misleading as a mismatch can happen in any provided AST file. Emitting a path for a file with a problem allows to disambiguate between multiple input files. Use generic term "AST file" because we don't always know a kind of the provided file (for example, see `ASTReader::readASTFileControlBlock`). rdar://65005546
2024-06-19[NFC] [Serialization] Unify how LocalDeclID can be createdChuanqi Xu1-1/+1
Now we can create a LocalDeclID directly with an integer without verifying. It may be hard to refactor if we want to change the way we serialize DeclIDs (See https://github.com/llvm/llvm-project/pull/95897). Also it is hard for us to debug if someday someone construct a LocalDeclID with an incorrect value. So in this patch, I tried to unify the way we can construct a LocalDeclID in ASTReader, where we will construct the LocalDeclID from the serialized data. Also, now we can verify the constructed LocalDeclID sooner in the new interface.
2024-05-17[clang] Introduce `SemaCodeCompletion` (#92311)Vlad Serebrennikov1-2/+3
This patch continues previous efforts to split `Sema` up, this time covering code completion. Context can be found in #84184. Dropping `Code` prefix from function names in `SemaCodeCompletion` would make sense, but I think this PR has enough changes already. As usual, formatting changes are done as a separate commit. Hopefully this helps with the review.
2024-05-06Reland "[Modules] No transitive source location change (#86912)"Chuanqi Xu1-2/+0
This relands 6c31104. The patch was reverted due to incorrectly introduced alignment. And the patch was re-commited after fixing the alignment issue. Following off are the original message: This is part of "no transitive change" patch series, "no transitive source location change". I talked this with @Bigcheese in the tokyo's WG21 meeting. The idea comes from @jyknight posted on LLVM discourse. That for: ``` // A.cppm export module A; ... // B.cppm export module B; import A; ... //--- C.cppm export module C; import C; ``` Almost every time A.cppm changes, we need to recompile `B`. Due to we think the source location is significant to the semantics. But it may be good if we can avoid recompiling `C` if the change from `A` wouldn't change the BMI of B. This patch only cares source locations. So let's focus on source location's example. We can see the full example from the attached test. ``` //--- A.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- A.v1.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- B.cppm export module B; import A; export int funcB() { return funcA(); } //--- C.cppm export module C; import A; export void testD() { C<int> c; c.func(); } ``` Here the only difference between `A.cppm` and `A.v1.cppm` is that `A.v1.cppm` has an additional blank line. Then the test shows that two BMI of `B.cppm`, one specified `-fmodule-file=A=A.pcm` and the other specified `-fmodule-file=A=A.v1.pcm`, should have the bit-wise same contents. However, it is a different story for C, since C instantiates templates from A, and the instantiation records the source information from module A, which is different from `A` and `A.v1`, so it is expected that the BMI `C.pcm` and `C.v1.pcm` can and should differ. To fully understand the patch, we need to understand how we encodes source locations and how we serialize and deserialize them. For source locations, we encoded them as: ``` | | | _____ base offset of an imported module | | | |_____ base offset of another imported module | | | | | ___ 0 ``` As the diagram shows, we encode the local (unloaded) source location from 0 to higher bits. And we allocate the space for source locations from the loaded modules from high bits to 0. Then the source locations from the loaded modules will be mapped to our source location space according to the allocated offset. For example, for, ``` // a.cppm export module a; ... // b.cppm export module b; import a; ... ``` Assuming the offset of a source location (let's name the location as `S`) in a.cppm is 45 and we will record the value `45` into the BMI `a.pcm`. Then in b.cppm, when we import a, the source manager will allocate a space for module 'a' (according to the recorded number of source locations) as the base offset of module 'a' in the current source location spaces. Let's assume the allocated base offset as 90 in this example. Then when we want to get the location in the current source location space for `S`, we can get it simply by adding `45` to `90` to `135`. Finally we can get the source location for `S` in module B as `135`. And when we want to write module `b`, we would also write the source location of `S` as `135` directly in the BMI. And to clarify the location `S` comes from module `a`, we also need to record the base offset of module `a`, 90 in the BMI of `b`. Then the problem comes. Since the base offset of module 'a' is computed by the number source locations in module 'a'. In module 'b', the recorded base offset of module 'a' will change every time the number of source locations in module 'a' increase or decrease. In other words, the contents of BMI of B will change every time the number of locations in module 'a' changes. This is pretty sensitive. Almost every change will change the number of locations. So this is the problem this patch want to solve. Let's continue with the existing design to understand what's going on. Another interesting case is: ``` // c.cppm export module c; import whatever; import a; import b; ... ``` In `c.cppm`, when we import `a`, we still need to allocate a base location offset for it, let's say the value becomes to `200` somehow. Then when we reach the location `S` recorded in module `b`, we need to translate it into the current source location space. The solution is quite simple, we can get it by `135 + (200 - 90) = 245`. In another word, the offset of a source location in current module can be computed as `Recorded Offset + Base Offset of the its module file - Recorded Base Offset`. Then we're almost done about how we handle the offset of source locations in serializers. From the abstract level, what we want to do is to remove the hardcoded base offset of imported modules and remain the ability to calculate the source location in a new module unit. To achieve this, we need to be able to find the module file owning a source location from the encoding of the source location. So in this patch, for each source location, we will store the local offset of the location and the module file index. For the above example, in `b.pcm`, the source location of `S` will be recorded as `135` directly. And in the new design, the source location of `S` will be recorded as `<1, 45>`. Here `1` stands for the module file index of `a` in module `b`. And `45` means the offset of `S` to the base offset of module `a`. So the trade-off here is that, to make the BMI more independent, we need to record more abstract information. And I feel it is worthy. The recompilation problem of modules is really annoying and there are still people complaining this. But if we can make this (including stopping other changes transitively), I think this may be a killer feature for modules. And from @Bigcheese , this should be helpful for clang explicit modules too. And the benchmarking side, I tested this patch against https://github.com/alibaba/async_simple/tree/CXX20Modules. No significant change on compilation time. The size of .pcm files becomes to 204M from 200M. I think the trade-off is pretty fair. I didn't use another slot to record the module file index. I tried to use the higher 32 bits of the existing source location encodings to store that information. This design may be safe. Since we use `unsigned` to store source locations but we use uint64_t in serialization. And generally `unsigned` is 32 bit width in most platforms. So it might not be a safe problem. Since all the bits we used to store the module file index is not used before. So the new encodings may be: ``` |-----------------------|-----------------------| | A | B | C | * A: 32 bit. The index of the module file in the module manager + 1. * The +1 here is necessary since we wish 0 stands for the current module file. * B: 31 bit. The offset of the source location to the module file * containing it. * C: The macro bit. We rotate it to the lowest bit so that we can save * some space in case the index of the module file is 0. ``` (The B and C is the existing raw encoding for source locations) Another reason to reuse the same slot of the source location is to reduce the impact of the patch. Since there are a lot of places assuming we can store and get a source location from a slot. And if I tried to add another slot, a lot of codes breaks. I don't feel it is worhty. Another impact of this decision is that, the existing small optimizations for encoding source location may be invalided. The key of the optimization is that we can turn large values into small values then we can use VBR6 format to reduce the size. But if we decided to put the module file index into the higher bits, then maybe it simply doesn't work. An example may be the `SourceLocationSequence` optimization. This will only affect the size of on-disk .pcm files. I don't expect this impact the speed and memory use of compilations. And seeing my small experiments above, I feel this trade off is worthy. The mental model for handling source location offsets is not so complex and I believe we can solve it by adding module file index to each stored source location. For the practical side, since the source location is pretty sensitive, and the patch can pass all the in-tree tests and a small scale projects, I feel it should be correct. I'll continue to work on no transitive decl change and no transitive identifier change (if matters) to achieve the goal to stop the propagation of unnecessary changes. But all of this depends on this patch. Since, clearly, the source locations are the most sensitive thing. --- The release nots and documentation will be added seperately.
2024-04-30Revert "[Modules] No transitive source location change (#86912)"Chuanqi Xu1-0/+2
This reverts commit 6c3110464bac3600685af9650269b0b2b8669d34. Required by the post commit comments: https://github.com/llvm/llvm-project/pull/86912
2024-04-30[Modules] No transitive source location change (#86912)Chuanqi Xu1-2/+0
This is part of "no transitive change" patch series, "no transitive source location change". I talked this with @Bigcheese in the tokyo's WG21 meeting. The idea comes from @jyknight posted on LLVM discourse. That for: ``` // A.cppm export module A; ... // B.cppm export module B; import A; ... //--- C.cppm export module C; import C; ``` Almost every time A.cppm changes, we need to recompile `B`. Due to we think the source location is significant to the semantics. But it may be good if we can avoid recompiling `C` if the change from `A` wouldn't change the BMI of B. # Motivation Example This patch only cares source locations. So let's focus on source location's example. We can see the full example from the attached test. ``` //--- A.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- A.v1.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- B.cppm export module B; import A; export int funcB() { return funcA(); } //--- C.cppm export module C; import A; export void testD() { C<int> c; c.func(); } ``` Here the only difference between `A.cppm` and `A.v1.cppm` is that `A.v1.cppm` has an additional blank line. Then the test shows that two BMI of `B.cppm`, one specified `-fmodule-file=A=A.pcm` and the other specified `-fmodule-file=A=A.v1.pcm`, should have the bit-wise same contents. However, it is a different story for C, since C instantiates templates from A, and the instantiation records the source information from module A, which is different from `A` and `A.v1`, so it is expected that the BMI `C.pcm` and `C.v1.pcm` can and should differ. # Internal perspective of status quo To fully understand the patch, we need to understand how we encodes source locations and how we serialize and deserialize them. For source locations, we encoded them as: ``` | | | _____ base offset of an imported module | | | |_____ base offset of another imported module | | | | | ___ 0 ``` As the diagram shows, we encode the local (unloaded) source location from 0 to higher bits. And we allocate the space for source locations from the loaded modules from high bits to 0. Then the source locations from the loaded modules will be mapped to our source location space according to the allocated offset. For example, for, ``` // a.cppm export module a; ... // b.cppm export module b; import a; ... ``` Assuming the offset of a source location (let's name the location as `S`) in a.cppm is 45 and we will record the value `45` into the BMI `a.pcm`. Then in b.cppm, when we import a, the source manager will allocate a space for module 'a' (according to the recorded number of source locations) as the base offset of module 'a' in the current source location spaces. Let's assume the allocated base offset as 90 in this example. Then when we want to get the location in the current source location space for `S`, we can get it simply by adding `45` to `90` to `135`. Finally we can get the source location for `S` in module B as `135`. And when we want to write module `b`, we would also write the source location of `S` as `135` directly in the BMI. And to clarify the location `S` comes from module `a`, we also need to record the base offset of module `a`, 90 in the BMI of `b`. Then the problem comes. Since the base offset of module 'a' is computed by the number source locations in module 'a'. In module 'b', the recorded base offset of module 'a' will change every time the number of source locations in module 'a' increase or decrease. In other words, the contents of BMI of B will change every time the number of locations in module 'a' changes. This is pretty sensitive. Almost every change will change the number of locations. So this is the problem this patch want to solve. Let's continue with the existing design to understand what's going on. Another interesting case is: ``` // c.cppm export module c; import whatever; import a; import b; ... ``` In `c.cppm`, when we import `a`, we still need to allocate a base location offset for it, let's say the value becomes to `200` somehow. Then when we reach the location `S` recorded in module `b`, we need to translate it into the current source location space. The solution is quite simple, we can get it by `135 + (200 - 90) = 245`. In another word, the offset of a source location in current module can be computed as `Recorded Offset + Base Offset of the its module file - Recorded Base Offset`. Then we're almost done about how we handle the offset of source locations in serializers. # The high level design of current patch From the abstract level, what we want to do is to remove the hardcoded base offset of imported modules and remain the ability to calculate the source location in a new module unit. To achieve this, we need to be able to find the module file owning a source location from the encoding of the source location. So in this patch, for each source location, we will store the local offset of the location and the module file index. For the above example, in `b.pcm`, the source location of `S` will be recorded as `135` directly. And in the new design, the source location of `S` will be recorded as `<1, 45>`. Here `1` stands for the module file index of `a` in module `b`. And `45` means the offset of `S` to the base offset of module `a`. So the trade-off here is that, to make the BMI more independent, we need to record more abstract information. And I feel it is worthy. The recompilation problem of modules is really annoying and there are still people complaining this. But if we can make this (including stopping other changes transitively), I think this may be a killer feature for modules. And from @Bigcheese , this should be helpful for clang explicit modules too. And the benchmarking side, I tested this patch against https://github.com/alibaba/async_simple/tree/CXX20Modules. No significant change on compilation time. The size of .pcm files becomes to 204M from 200M. I think the trade-off is pretty fair. # Some low level details I didn't use another slot to record the module file index. I tried to use the higher 32 bits of the existing source location encodings to store that information. This design may be safe. Since we use `unsigned` to store source locations but we use uint64_t in serialization. And generally `unsigned` is 32 bit width in most platforms. So it might not be a safe problem. Since all the bits we used to store the module file index is not used before. So the new encodings may be: ``` |-----------------------|-----------------------| | A | B | C | * A: 32 bit. The index of the module file in the module manager + 1. The +1 here is necessary since we wish 0 stands for the current module file. * B: 31 bit. The offset of the source location to the module file containing it. * C: The macro bit. We rotate it to the lowest bit so that we can save some space in case the index of the module file is 0. ``` (The B and C is the existing raw encoding for source locations) Another reason to reuse the same slot of the source location is to reduce the impact of the patch. Since there are a lot of places assuming we can store and get a source location from a slot. And if I tried to add another slot, a lot of codes breaks. I don't feel it is worhty. Another impact of this decision is that, the existing small optimizations for encoding source location may be invalided. The key of the optimization is that we can turn large values into small values then we can use VBR6 format to reduce the size. But if we decided to put the module file index into the higher bits, then maybe it simply doesn't work. An example may be the `SourceLocationSequence` optimization. This will only affect the size of on-disk .pcm files. I don't expect this impact the speed and memory use of compilations. And seeing my small experiments above, I feel this trade off is worthy. # Correctness The mental model for handling source location offsets is not so complex and I believe we can solve it by adding module file index to each stored source location. For the practical side, since the source location is pretty sensitive, and the patch can pass all the in-tree tests and a small scale projects, I feel it should be correct. # Future Plans I'll continue to work on no transitive decl change and no transitive identifier change (if matters) to achieve the goal to stop the propagation of unnecessary changes. But all of this depends on this patch. Since, clearly, the source locations are the most sensitive thing. --- The release nots and documentation will be added seperately.
2024-04-25[NFC] [ASTUnit] [Serialization] Transalte local decl ID to global decl ID ↵Chuanqi Xu1-4/+3
before consuming Discovered from https://github.com/llvm/llvm-project/commit/d86cc73bbfd9a22d9a0d498d72c9b2ee235128e9. There is a potential issue of using DeclID in ASTUnit. ASTUnit may record the declaration ID from ASTWriter. And after loading the preamble, the ASTUnit may consume the recorded declaration ID directly in ExternalASTSource. This is not good. According to the design, all local declaration ID consumed in ASTReader need to be translated by `ASTReader::getGlobaldeclID()`. This will be problematic if we changed the encodings of declaration IDs or if we make preamble to work more complexly.
2024-04-25[NFC] [Serialization] Avoid using DeclID directly as much as possibleChuanqi Xu1-3/+5
This patch tries to remove all the direct use of DeclID except the real low level reading and writing. All the use of DeclID is converted to the use of LocalDeclID or GlobalDeclID. This is helpful to increase the readability and type safety.
2024-04-25Revert "[NFC] [Serialization] Avoid using DeclID directly as much as possible"Chuanqi Xu1-5/+3
This reverts commit 42070a5c092ed420bf92ebf38229c594885e94c7. I forgot to touch lldb.
2024-04-25[NFC] [Serialization] Avoid using DeclID directly as much as possibleChuanqi Xu1-3/+5
This patch tries to remove all the direct use of DeclID except the real low level reading and writing. All the use of DeclID is converted to the use of LocalDeclID or GlobalDeclID. This is helpful to increase the readability and type safety.
2024-04-25[NFC] Move DeclID from serialization/ASTBitCodes.h to AST/DeclID.h (#89873)Chuanqi Xu1-2/+2
Previously, the DeclID is defined in serialization/ASTBitCodes.h under clang::serialization namespace. However, actually the DeclID is not purely used in serialization part. The DeclID is already widely used in AST and all around the clang project via classes like `LazyPtrDecl` or calling `ExternalASTSource::getExernalDecl()`. All such uses are via the raw underlying type of `DeclID` as `uint32_t`. This is not pretty good. This patch moves the DeclID class family to a new header `AST/DeclID.h` so that the whole project can use the wrapped class `DeclID`, `GlobalDeclID` and `LocalDeclID` instead of the raw underlying type. This can improve the readability and the type safety.
2024-02-23[C++20] [Modules] Allow to compile a pcm with and without -fPICChuanqi Xu1-2/+13
seperately We can compile a module unit in 2 phase compilaton: ``` clang++ -std=c++20 a.cppm --precompile -o a.pcm clang++ -std=c++20 a.pcm -c -o a.o ``` And it is a general requirement that we need to compile a translation unit with and without -fPIC for static and shared libraries. But for C++20 modules with 2 phase compilation, it may be waste of time to compile them 2 times completely. It may be fine to generate one BMI and compile it with and without -fPIC seperately. e.g., ``` clang++ -std=c++20 a.cppm --precompile -o a.pcm clang++ -std=c++20 a.pcm -c -o a.o clang++ -std=c++20 a.pcm -c -fPIC -o a-PIC.o ``` Then we can save the time to parse a.cppm repeatedly.
2023-11-28[clang] Remove unused argument. NFC. (#73594)Juergen Ributzka1-4/+3
2023-11-09[C++20] [Modules] Allow export from language linkageChuanqi Xu1-1/+1
Close https://github.com/llvm/llvm-project/issues/71347 Previously I misread the concept of module purview. I thought if a declaration attached to a unnamed module, it can't be part of the module purview. But after the issue report, I recognized that module purview is more of a concept about locations instead of semantics. Concretely, the things in the language linkage after module declarations can be exported. This patch refactors `Module::isModulePurview()` and introduces some possible code cleanups.
2023-10-06Revert "Revert "Fixes and closes #53952. Setting the ASTHasCompilerErrors ↵Aaron Ballman1-12/+5
member variable correctly based on the PP diagnostics. (#68127)"" This reverts commit a6acf3fd49a20c570a390af2a3c84e10b9545b68 and relands a50e63b38b931d945f97eac882278068221eca17. The original revert was done by mistake.