Skip to content

[clang-repl] Teach clang-repl how to load PCHs. #94166

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions clang/include/clang/CodeGen/ModuleBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ namespace CodeGen {
class CodeGenerator : public ASTConsumer {
virtual void anchor();

protected:
/// True if we've finished generating IR. This prevents us from generating
/// additional LLVM IR after emitting output in HandleTranslationUnit. This
/// can happen when Clang plugins trigger additional AST deserialization.
bool IRGenFinished = false;

public:
/// Return an opaque reference to the CodeGenModule object, which can
/// be used in various secondary APIs. It is valid as long as the
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/CodeGen/BackendConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ class BackendConsumer : public ASTConsumer {
llvm::Timer LLVMIRGeneration;
unsigned LLVMIRGenerationRefCount;

/// True if we've finished generating IR. This prevents us from generating
/// additional LLVM IR after emitting output in HandleTranslationUnit. This
/// can happen when Clang plugins trigger additional AST deserialization.
bool IRGenFinished = false;

bool TimerIsEnabled = false;

std::unique_ptr<CodeGenerator> Gen;
Expand Down
6 changes: 1 addition & 5 deletions clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ void BackendConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
}

void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) {
// Ignore interesting decls from the AST reader after IRGen is finished.
if (!IRGenFinished)
HandleTopLevelDecl(D);
HandleTopLevelDecl(D);
}

// Links each entry in LinkModules into our module. Returns true on error.
Expand Down Expand Up @@ -280,8 +278,6 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
}

IRGenFinished = true;
}

// Silently ignore if we weren't initialized for some reason.
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/CodeGen/ModuleBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ namespace {
assert(!M && "Replacing existing Module?");
M.reset(new llvm::Module(ExpandModuleName(ModuleName, CodeGenOpts), C));

IRGenFinished = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is IR gen finished when we're just starting the module?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a double negation: it is /not/ finished when we start a new module.


std::unique_ptr<CodeGenModule> OldBuilder = std::move(Builder);

Initialize(*Ctx);
Expand Down Expand Up @@ -179,6 +181,10 @@ namespace {
}

bool HandleTopLevelDecl(DeclGroupRef DG) override {
// Ignore interesting decls from the AST reader after IRGen is finished.
if (IRGenFinished)
return true; // We can't CodeGen more but pass to other consumers.

// FIXME: Why not return false and abort parsing?
if (Diags.hasUnrecoverableErrorOccurred())
return true;
Expand Down Expand Up @@ -282,6 +288,7 @@ namespace {
}

void HandleTranslationUnit(ASTContext &Ctx) override {

// Release the Builder when there is no error.
if (!Diags.hasUnrecoverableErrorOccurred() && Builder)
Builder->Release();
Expand All @@ -292,8 +299,9 @@ namespace {
if (Builder)
Builder->clear();
M.reset();
return;
}

IRGenFinished = true;
}

void AssignInheritanceModel(CXXRecordDecl *RD) override {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
Consumer = &CI->getASTConsumer();
P.reset(
new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false));

if (ExternalASTSource *External = CI->getASTContext().getExternalSource())
External->StartTranslationUnit(Consumer);

P->Initialize();

// An initial PTU is needed as CUDA includes some headers automatically
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Interpreter/execute-pch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// REQUIRES: host-supports-jit
// UNSUPPORTED: system-aix

// RUN: rm -f %t.pch
// RUN: %clang_cc1 -fmax-type-align=16 -pic-level 2 -fdeprecated-macro -stack-protector 1 -fblocks -fskip-odr-check-in-gmf -fexceptions -fcxx-exceptions -fgnuc-version=0 -triple=%target_triple -DPCH -fincremental-extensions -emit-pch -x c++-header -o %t.pch %s
// RUN: clang-repl -Xcc -fgnuc-version=0 -Xcc -triple=%target_triple -Xcc -include-pch -Xcc %t.pch '#include "%s"' | FileCheck %s
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weliveindetail, it seems that clang-repl prefers the process triple:

std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();

What should we do here? Should we implement a lit version of host-supports-jit but host-jit-triple? Is there something smarter we could do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When -triple is passed explicitly I'd expect it to override the process triple. Is there a reason not to do that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How we can get the “right” triple from clang? And yes, sometimes the build can be configured in an odd way (we have some bots) where the triple from clang is different from the triple of the JIT. Unfortunately, we did not find a way to suppress these cases with a good lit clause last time we dealt with them.


#ifdef PCH
int f_pch() { return 5; }
#endif // PCH

extern "C" int printf(const char *, ...);
auto r1 = printf("f_pch = %d\n", f_pch());
// CHECK: f_pch = 5
Loading