mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Fundamentally, this uses forward declarations of Clang types to reduce the overall compile time cost of Clang headers across the codebase. Tracing and profiling showed ~2s of every check TU's ~8-12s compile time going just to parsing Clang frontend and AST headers pulled in via a few sem_ir and check headers that only use the Clang types by pointer or reference: - sem_ir/cpp_file.h (reached via sem_ir/file.h by ~150 TUs) included clang/Frontend/CompilerInstance.h, clang/CodeGen/ModuleBuilder.h, clang/AST/Mangle.h, and llvm/IR/Module.h. CppFile's accessors move out of line to a new cpp_file.cpp and the header now forward-declares the Clang types. - check/cpp/context.h (reached via check/context.h by ~100 TUs) included clang/Frontend/FrontendAction.h and clang/Parse/Parser.h, pulling in clang's Sema.h and ASTUnit.h. - sem_ir/clang_decl.h included clang/AST/Decl.h; the three small functions that need complete Clang types move out of line. - sem_ir/cpp_overload_set.h included clang/Sema/Overload.h solely for the three-field OverloadCandidateSet::OperatorRewriteInfo, which is now mirrored as CppOverloadSet::OperatorRewriteInfo, and clang/AST/Decl.h solely for a pointer. - sem_ir/name_scope.h's clang/AST/DeclBase.h include was vestigial. TUs (and more narrowly included headers) that genuinely use the Clang definitions now include the Clang headers directly. Representative compile times (fastbuild, aarch64), combined with the preceding instantiation-cost changes, relative to trunk: - check/eval.cpp: 11.85s -> 6.94s (-41%) - check/handle_operator.cpp: 7.71s -> 3.30s (-57%) - language_server.cpp: 6.68s -> 3.16s (-53%) - lower/handle.cpp: 6.75s -> 3.66s (-46%) - sem_ir/file.cpp: 8.60s -> 6.11s (-29%) - driver.cpp: 6.68s -> 4.78s (-28%) Measured full-rebuild impact (316 first-party TUs, fastbuild): -689.5s CPU, -29.9% relative to trunk. Assisted-by: Claude
129 lines
5.8 KiB
C++
129 lines
5.8 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_
|
|
|
|
#include "clang/AST/Type.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/check/convert.h"
|
|
#include "toolchain/check/diagnostic_helpers.h"
|
|
#include "toolchain/diagnostics/emitter.h"
|
|
#include "toolchain/sem_ir/clang_decl.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace clang {
|
|
class CompilerInvocation;
|
|
class IdentifierInfo;
|
|
class VarDecl;
|
|
} // namespace clang
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// Returns whether the given function is an object member function. This is true
|
|
// if it's a non-static member function and not a constructor. Object member
|
|
// functions correspond to Carbon functions with a `self` parameter.
|
|
// TODO: Find a better home for this function.
|
|
auto IsObjectMemberFunction(const clang::FunctionDecl& decl) -> bool;
|
|
|
|
// Generates a C++ header that includes the imported cpp files, parses it,
|
|
// generates the AST from it and links `SemIR::File` to it. Reports C++ errors
|
|
// and warnings. If successful, adds a `Cpp` namespace.
|
|
auto ImportCpp(Context& context,
|
|
llvm::ArrayRef<Parse::Tree::PackagingNames> imports,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
|
|
llvm::LLVMContext* llvm_context,
|
|
std::shared_ptr<clang::CompilerInvocation> invocation) -> void;
|
|
|
|
// Given a clang declaration ID that was previously imported into another file,
|
|
// returns the corresponding clang declaration key in the current context.
|
|
// Produces an error and returns nullopt on failure.
|
|
auto FindCorrespondingClangDeclKey(Context& context, SemIR::LocId loc_id,
|
|
const SemIR::File& file,
|
|
SemIR::ClangDeclId clang_decl_id)
|
|
-> std::optional<SemIR::ClangDeclKey>;
|
|
|
|
// Imports a declaration into the current context that was previously imported
|
|
// into another file.
|
|
auto ImportCppDeclFromFile(Context& context, SemIR::LocId loc_id,
|
|
const SemIR::File& file,
|
|
SemIR::ClangDeclId clang_decl_id)
|
|
-> SemIR::ConstantId;
|
|
|
|
// Imports a constant into the current context that was previously imported into
|
|
// another file.
|
|
auto ImportCppConstantFromFile(Context& context, SemIR::LocId loc_id,
|
|
const SemIR::File& file, SemIR::InstId inst_id)
|
|
-> SemIR::ConstantId;
|
|
|
|
// Imports a declaration from Clang to Carbon. If successful, returns the new
|
|
// Carbon declaration `InstId`. If the declaration was already imported, returns
|
|
// the mapped instruction. All unimported dependencies are imported first.
|
|
auto ImportCppDecl(Context& context, SemIR::LocId loc_id,
|
|
SemIR::ClangDeclKey key) -> SemIR::InstId;
|
|
|
|
// Imports a function declaration from Clang to Carbon. If successful, returns
|
|
// the new Carbon function declaration `InstId`. If the declaration was already
|
|
// imported, returns the mapped instruction.
|
|
inline auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id,
|
|
clang::FunctionDecl* clang_decl,
|
|
SemIR::ClangDeclSignatureId signature_id)
|
|
-> SemIR::InstId {
|
|
return ImportCppDecl(
|
|
context, loc_id,
|
|
SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature_id));
|
|
}
|
|
|
|
// Imports a function declaration from Clang to Carbon. If successful, returns
|
|
// the new Carbon function declaration `InstId`. If the declaration was already
|
|
// imported, returns the mapped instruction. All unimported dependencies are
|
|
// imported first.
|
|
auto ImportCppType(Context& context, SemIR::LocId loc_id, clang::QualType type)
|
|
-> TypeExpr;
|
|
|
|
// Imports an overloaded function set from Clang to Carbon.
|
|
auto ImportCppOverloadSet(
|
|
Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,
|
|
SemIR::NameId name_id, clang::CXXRecordDecl* naming_class,
|
|
clang::UnresolvedSet<4>&& overload_set,
|
|
SemIR::CppOverloadSet::OperatorRewriteInfo operator_rewrite_info)
|
|
-> SemIR::InstId;
|
|
|
|
// Looks up the given name in the Clang AST generated when importing C++ code
|
|
// and returns a lookup result. If using the injected class name (`X.X()`),
|
|
// imports the class constructor as a function named as the class.
|
|
auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
|
|
SemIR::NameScopeId scope_id, SemIR::NameId name_id)
|
|
-> SemIR::ScopeLookupResult;
|
|
|
|
// Given a Carbon class declaration that was imported from some kind of C++
|
|
// declaration, such as a class or enum, attempt to import a corresponding class
|
|
// definition. Returns true if nothing went wrong (whether or not a definition
|
|
// could be imported), false if a diagnostic was produced.
|
|
auto ImportClassDefinitionForClangDecl(Context& context,
|
|
SemIR::ClassId class_id,
|
|
SemIR::ClangDeclId clang_decl_id)
|
|
-> bool;
|
|
|
|
// Gets the identifier info for a name. Returns `nullptr` if the name is not an
|
|
// identifier name.
|
|
auto GetClangIdentifierInfo(Context& context, SemIR::NameId name_id)
|
|
-> clang::IdentifierInfo*;
|
|
|
|
// Maps from a `VarStorage` instruction to a `clang::VarDecl`. Returns
|
|
// null if the instruction is not a `VarStorage`, or if its contents
|
|
// cannot be mapped to a `clang::VarDecl`.
|
|
auto GetAsClangVarDecl(Context& context, SemIR::InstId inst_id)
|
|
-> clang::VarDecl*;
|
|
|
|
// Maps a Clang name to a Carbon `NameId`.
|
|
auto AddIdentifierName(Context& context, llvm::StringRef name) -> SemIR::NameId;
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_
|