Skip to content

Commit 2aa7527

Browse files
committed
[clang-repl] Simplify the value printing logic to enable out-of-process.
This patch improves the design of the IncrementalParser and Interpreter classes. Now the incremental parser is only responsible for building the partial translation unit declaration and the AST, while the Interpreter fills in the lower level llvm::Module and other JIT-related infrastructure. Finally the Interpreter class now orchestrates the AST and the LLVM IR with the IncrementalParser and IncrementalExecutor classes. The design improvement allows us to rework some of the logic that extracts an interpreter value into the clang::Value object. The new implementation simplifies use-cases which are used for out-of-process execution by allowing interpreter to be inherited or customized with an clang::ASTConsumer. This change will enable completing the pretty printing work which is in #84769
1 parent b4feb26 commit 2aa7527

13 files changed

+707
-795
lines changed

clang/include/clang/Frontend/MultiplexConsumer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class MultiplexConsumer : public SemaConsumer {
5353
public:
5454
// Takes ownership of the pointers in C.
5555
MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>> C);
56+
MultiplexConsumer(std::unique_ptr<ASTConsumer> C);
5657
~MultiplexConsumer() override;
5758

5859
// ASTConsumer
@@ -80,7 +81,7 @@ class MultiplexConsumer : public SemaConsumer {
8081
void InitializeSema(Sema &S) override;
8182
void ForgetSema() override;
8283

83-
private:
84+
protected:
8485
std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these.
8586
std::unique_ptr<MultiplexASTMutationListener> MutationListener;
8687
std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener;

clang/include/clang/Interpreter/Interpreter.h

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@
1414
#ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
1515
#define LLVM_CLANG_INTERPRETER_INTERPRETER_H
1616

17-
#include "clang/AST/Decl.h"
1817
#include "clang/AST/GlobalDecl.h"
1918
#include "clang/Interpreter/PartialTranslationUnit.h"
2019
#include "clang/Interpreter/Value.h"
21-
#include "clang/Sema/Ownership.h"
2220

2321
#include "llvm/ADT/DenseMap.h"
2422
#include "llvm/ExecutionEngine/JITSymbol.h"
@@ -38,6 +36,9 @@ class ThreadSafeContext;
3836
namespace clang {
3937

4038
class CompilerInstance;
39+
class CodeGenerator;
40+
class CXXRecordDecl;
41+
class Decl;
4142
class IncrementalExecutor;
4243
class IncrementalParser;
4344

@@ -77,42 +78,43 @@ class IncrementalCompilerBuilder {
7778
llvm::StringRef CudaSDKPath;
7879
};
7980

80-
/// Generate glue code between the Interpreter's built-in runtime and user code.
81-
class RuntimeInterfaceBuilder {
82-
public:
83-
virtual ~RuntimeInterfaceBuilder() = default;
84-
85-
using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder,
86-
Expr *, ArrayRef<Expr *>);
87-
virtual TransformExprFunction *getPrintValueTransformer() = 0;
88-
};
81+
class IncrementalAction;
82+
class InProcessPrintingASTConsumer;
8983

9084
/// Provides top-level interfaces for incremental compilation and execution.
9185
class Interpreter {
86+
friend class Value;
87+
friend InProcessPrintingASTConsumer;
88+
9289
std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx;
90+
/// Long-lived, incremental parsing action.
91+
std::unique_ptr<IncrementalAction> Act;
9392
std::unique_ptr<IncrementalParser> IncrParser;
9493
std::unique_ptr<IncrementalExecutor> IncrExecutor;
95-
std::unique_ptr<RuntimeInterfaceBuilder> RuntimeIB;
9694

9795
// An optional parser for CUDA offloading
9896
std::unique_ptr<IncrementalParser> DeviceParser;
9997

98+
/// List containing every information about every incrementally parsed piece
99+
/// of code.
100+
std::list<PartialTranslationUnit> PTUs;
101+
100102
unsigned InitPTUSize = 0;
101103

102104
// This member holds the last result of the value printing. It's a class
103105
// member because we might want to access it after more inputs. If no value
104106
// printing happens, it's in an invalid state.
105107
Value LastValue;
106108

107-
// Add a call to an Expr to report its result. We query the function from
108-
// RuntimeInterfaceBuilder once and store it as a function pointer to avoid
109-
// frequent virtual function calls.
110-
RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr;
109+
/// When CodeGen is created the first llvm::Module gets cached in many places
110+
/// and we must keep it alive.
111+
std::unique_ptr<llvm::Module> CachedInCodeGenModule;
111112

112113
protected:
113114
// Derived classes can use an extended interface of the Interpreter.
114115
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err,
115-
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
116+
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
117+
std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);
116118

117119
// Create the internal IncrementalExecutor, or re-create it after calling
118120
// ResetExecutor().
@@ -122,15 +124,8 @@ class Interpreter {
122124
// JIT engine. In particular, it doesn't run cleanup or destructors.
123125
void ResetExecutor();
124126

125-
// Lazily construct the RuntimeInterfaceBuilder. The provided instance will be
126-
// used for the entire lifetime of the interpreter. The default implementation
127-
// targets the in-process __clang_Interpreter runtime. Override this to use a
128-
// custom runtime.
129-
virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface();
130-
131127
public:
132128
virtual ~Interpreter();
133-
134129
static llvm::Expected<std::unique_ptr<Interpreter>>
135130
create(std::unique_ptr<CompilerInstance> CI);
136131
static llvm::Expected<std::unique_ptr<Interpreter>>
@@ -145,7 +140,6 @@ class Interpreter {
145140
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
146141
llvm::Error Execute(PartialTranslationUnit &T);
147142
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
148-
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
149143

150144
/// Undo N previous incremental inputs.
151145
llvm::Error Undo(unsigned N = 1);
@@ -167,8 +161,6 @@ class Interpreter {
167161
llvm::Expected<llvm::orc::ExecutorAddr>
168162
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
169163

170-
enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };
171-
172164
const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
173165
return ValuePrintingInfo;
174166
}
@@ -178,7 +170,14 @@ class Interpreter {
178170
private:
179171
size_t getEffectivePTUSize() const;
180172
void markUserCodeStart();
173+
llvm::Expected<Expr *> AttachValuePrinting(Expr *E);
174+
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
175+
176+
CodeGenerator *getCodeGen() const;
177+
std::unique_ptr<llvm::Module> GenModule();
181178

179+
// A cache for the compiled destructors used to for de-allocation of managed
180+
// clang::Values.
182181
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
183182

184183
llvm::SmallVector<Expr *, 4> ValuePrintingInfo;

clang/lib/Frontend/MultiplexConsumer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,13 @@ MultiplexConsumer::MultiplexConsumer(
298298
}
299299
}
300300

301+
MultiplexConsumer::MultiplexConsumer(std::unique_ptr<ASTConsumer> C)
302+
: MultiplexConsumer([](std::unique_ptr<ASTConsumer> Consumer) {
303+
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
304+
Consumers.push_back(std::move(Consumer));
305+
return Consumers;
306+
}(std::move(C))) {}
307+
301308
MultiplexConsumer::~MultiplexConsumer() {}
302309

303310
void MultiplexConsumer::Initialize(ASTContext &Context) {

clang/lib/Interpreter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_clang_library(clangInterpreter
2222
IncrementalExecutor.cpp
2323
IncrementalParser.cpp
2424
Interpreter.cpp
25+
InterpreterValuePrinter.cpp
2526
InterpreterUtils.cpp
2627
Value.cpp
2728
${WASM_SRC}

clang/lib/Interpreter/DeviceOffload.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/Basic/TargetOptions.h"
1616
#include "clang/CodeGen/ModuleBuilder.h"
1717
#include "clang/Frontend/CompilerInstance.h"
18+
#include "clang/Interpreter/PartialTranslationUnit.h"
1819

1920
#include "llvm/IR/LegacyPassManager.h"
2021
#include "llvm/IR/Module.h"
@@ -24,11 +25,10 @@
2425
namespace clang {
2526

2627
IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
27-
Interpreter &Interp, std::unique_ptr<CompilerInstance> Instance,
28-
IncrementalParser &HostParser, llvm::LLVMContext &LLVMCtx,
28+
std::unique_ptr<CompilerInstance> Instance, IncrementalParser &HostParser,
2929
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
30-
llvm::Error &Err)
31-
: IncrementalParser(Interp, std::move(Instance), LLVMCtx, Err),
30+
llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
31+
: IncrementalParser(std::move(Instance), Err), PTUs(PTUs),
3232
HostParser(HostParser), VFS(FS) {
3333
if (Err)
3434
return;
@@ -41,7 +41,7 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
4141
}
4242
}
4343

44-
llvm::Expected<PartialTranslationUnit &>
44+
llvm::Expected<TranslationUnitDecl *>
4545
IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
4646
auto PTU = IncrementalParser::Parse(Input);
4747
if (!PTU)

clang/lib/Interpreter/DeviceOffload.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
#include "llvm/Support/VirtualFileSystem.h"
1919

2020
namespace clang {
21-
21+
struct PartialTranslationUnit;
2222
class IncrementalCUDADeviceParser : public IncrementalParser {
23+
const std::list<PartialTranslationUnit> &PTUs;
24+
2325
public:
2426
IncrementalCUDADeviceParser(
25-
Interpreter &Interp, std::unique_ptr<CompilerInstance> Instance,
26-
IncrementalParser &HostParser, llvm::LLVMContext &LLVMCtx,
27+
std::unique_ptr<CompilerInstance> Instance, IncrementalParser &HostParser,
2728
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS,
28-
llvm::Error &Err);
29+
llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs);
2930

30-
llvm::Expected<PartialTranslationUnit &>
31-
Parse(llvm::StringRef Input) override;
31+
llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override;
3232

33-
// Generate PTX for the last PTU
33+
// Generate PTX for the last PTU.
3434
llvm::Expected<llvm::StringRef> GeneratePTX();
3535

3636
// Generate fatbinary contents in memory

clang/lib/Interpreter/IncrementalExecutor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,4 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
118118
return SymOrErr->getAddress();
119119
}
120120

121-
} // end namespace clang
121+
} // namespace clang

0 commit comments

Comments
 (0)