Skip to content

[clang-repl] Include consistency using the default clang actions. #116610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion clang/include/clang/Frontend/FrontendAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -185,7 +186,12 @@ class FrontendAction {
virtual bool usesPreprocessorOnly() const = 0;

/// For AST-based actions, the kind of translation unit we're handling.
virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
virtual TranslationUnitKind getTranslationUnitKind() {
// The ASTContext, if exists, knows the exact TUKind of the frondend.
if (Instance && Instance->hasASTContext())
return Instance->getASTContext().TUKind;
return TU_Complete;
}

/// Does this action support use with PCH?
virtual bool hasPCHSupport() const { return true; }
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ class Interpreter {

CodeGenerator *getCodeGen() const;
std::unique_ptr<llvm::Module> GenModule();
PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU);
PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
std::unique_ptr<llvm::Module> M = {});

// A cache for the compiled destructors used to for de-allocation of managed
// clang::Values.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Interpreter/PartialTranslationUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ struct PartialTranslationUnit {

/// The llvm IR produced for the input.
std::unique_ptr<llvm::Module> TheModule;
bool operator==(const PartialTranslationUnit &other) {
return other.TUPart == TUPart && other.TheModule == TheModule;
}
};
} // namespace clang

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ set(LLVM_LINK_COMPONENTS
Support
Target
TargetParser
)
TransformUtils
)

if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS)
set(WASM_SRC Wasm.cpp)
Expand Down
71 changes: 43 additions & 28 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule

#define DEBUG_TYPE "clang-repl"

using namespace clang;
// FIXME: Figure out how to unify with namespace init_convenience from
Expand Down Expand Up @@ -339,19 +342,8 @@ class IncrementalAction : public WrapperFrontendAction {
}

void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
assert(CI.hasPreprocessor() && "No PP!");

// Use a code completion consumer?
CodeCompleteConsumer *CompletionConsumer = nullptr;
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();

Preprocessor &PP = CI.getPreprocessor();
PP.EnterMainSourceFile();

if (!CI.hasSema())
CI.createSema(getTranslationUnitKind(), CompletionConsumer);
WrapperFrontendAction::ExecuteAction();
getCompilerInstance().getSema().CurContext = nullptr;
}

// Do not terminate after processing the input. This allows us to keep various
Expand Down Expand Up @@ -385,27 +377,29 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
return;
CI->ExecuteAction(*Act);

ASTContext &C = CI->getASTContext();

IncrParser = std::make_unique<IncrementalParser>(*CI, ErrOut);

if (ErrOut)
return;

if (getCodeGen()) {
CachedInCodeGenModule = GenModule();
// The initial PTU is filled by `-include` or by CUDA includes
// automatically.
if (!CI->getPreprocessorOpts().Includes.empty()) {
// We can't really directly pass the CachedInCodeGenModule to the Jit
// because it will steal it, causing dangling references as explained in
// Interpreter::Execute
auto M = llvm::CloneModule(*CachedInCodeGenModule);
ASTContext &C = CI->getASTContext();
RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
}
if (llvm::Error Err = CreateExecutor()) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}
}

// The initial PTU is filled by `-include` or by CUDA includes automatically.
RegisterPTU(C.getTranslationUnitDecl());

// Prepare the IncrParser for input.
llvm::cantFail(Parse(""));

// Not all frontends support code-generation, e.g. ast-dump actions don't
if (getCodeGen()) {
// Process the PTUs that came from initialization. For example -include will
Expand Down Expand Up @@ -535,14 +529,25 @@ size_t Interpreter::getEffectivePTUSize() const {
return PTUs.size() - InitPTUSize;
}

PartialTranslationUnit &Interpreter::RegisterPTU(TranslationUnitDecl *TU) {
PartialTranslationUnit &
Interpreter::RegisterPTU(TranslationUnitDecl *TU,
std::unique_ptr<llvm::Module> M /*={}*/) {
PTUs.emplace_back(PartialTranslationUnit());
PartialTranslationUnit &LastPTU = PTUs.back();
LastPTU.TUPart = TU;

if (std::unique_ptr<llvm::Module> M = GenModule())
LastPTU.TheModule = std::move(M);
if (!M)
M = GenModule();

assert((!getCodeGen() || M) && "Must have a llvm::Module at this point");

LastPTU.TheModule = std::move(M);
LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1
<< ": [TU=" << LastPTU.TUPart);
if (LastPTU.TheModule)
LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " ("
<< LastPTU.TheModule->getName() << ")");
LLVM_DEBUG(llvm::dbgs() << "]\n");
return LastPTU;
}

Expand Down Expand Up @@ -615,6 +620,14 @@ void Interpreter::ResetExecutor() { IncrExecutor.reset(); }

llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
assert(T.TheModule);
LLVM_DEBUG(llvm::dbgs()
<< "execute-ptu "
<< ((std::find(PTUs.begin(), PTUs.end(), T) != PTUs.end())
? std::distance(PTUs.begin(),
std::find(PTUs.begin(), PTUs.end(), T))
: -1)
<< ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() << " ("
<< T.TheModule->getName() << ")]\n");
if (!IncrExecutor) {
auto Err = CreateExecutor();
if (Err)
Expand Down Expand Up @@ -723,10 +736,12 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
// of the module which does not map well to CodeGen's design. To work this
// around we created an empty module to make CodeGen happy. We should make
// sure it always stays empty.
assert((!CachedInCodeGenModule || (CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
assert(((!CachedInCodeGenModule ||
!getCompilerInstance()->getPreprocessorOpts().Includes.empty()) ||
(CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
"CodeGen wrote to a readonly module");
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
Expand Down
Loading