mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-29 08:44:57 +01:00
Background: https://docs.google.com/document/d/1wi85FRiWh4X9A-gCYMVGKR40-q5fM6-3JaSpePk-XCY/edit?usp=sharing And specifically this work is essentially an alternative to #5543 Clang's code generation is implemented through an ASTListener (clang::CodeGenerator) that is attached throughout Clang's parsing/sema/code generation phases and acts on Clang AST incrementally throughout that process. Prior to this patch, Carbon has only created the CodeGenerator during Carbon's `lower` phase, missing out on key callbacks that would be made by Clang during `check`. Some of these issues were addressed by #6237 and #6483 - but there were still remaining cases where the delayed processing lead to missing functionality. With #6483 much of the Clang code that made multithreaded complexity of #5543 is no longer present, and we have access to the point of ASTListener registration so we can register the CodeGenerator there and consume its resulting llvm::Module during lower. Examples of some of the bugs this addresses are seen in the linked doc, and checked in as tests in this change in `clang_code_generator_callbacks.carbon` An indicental bug that's also fixed, and caused all the other test case churn, is that the `CodeGenerator` created during `lower` wasn't getting passed the Clang `CodeGenOpts` and was creating its own default - so, most notably, optimization flags were not respected. This meant that the LLVM IR from Clang was always -O0 style IR (optnone, no inlinehint, no TBAA, etc). With this change, now the Clang IRGen gets the real `CodeGenOpts` and respects optimization/other flags specified there. This is only meant to be a rough proof of concept - I'm totally open to reworking this in any way (even quite substantially) if folks have ideas about how this should be implemented most generally/elegantly/etc.
80 lines
3.7 KiB
C++
80 lines
3.7 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 "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/diagnostic_emitter.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// 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;
|
|
|
|
// 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,
|
|
int num_params) -> SemIR::InstId {
|
|
return ImportCppDecl(
|
|
context, loc_id,
|
|
SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, num_params));
|
|
}
|
|
|
|
// 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,
|
|
clang::OverloadCandidateSet::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::LocId loc_id,
|
|
SemIR::ClassId class_id,
|
|
SemIR::ClangDeclId clang_decl_id)
|
|
-> bool;
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_
|