Skip to content

Commit 0f6d68c

Browse files
committed
[clang-repl] Implement value printing of custom types.
The work started as part of https://reviews.llvm.org/D146809 This patch reworks a lot of the infrastructure to enable printing of types for out-of-process execution on embedded devices.
1 parent b4feb26 commit 0f6d68c

26 files changed

+2197
-823
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
10991099
bool isInSameModule(const Module *M1, const Module *M2);
11001100

11011101
TranslationUnitDecl *getTranslationUnitDecl() const {
1102+
assert(TUDecl->getMostRecentDecl() == TUDecl &&
1103+
"The active TU is not current one!");
11021104
return TUDecl->getMostRecentDecl();
11031105
}
11041106
void addTranslationUnitDecl() {

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: 48 additions & 35 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,56 @@ 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+
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
99+
100+
/// List containing every information about every incrementally parsed piece
101+
/// of code.
102+
std::list<PartialTranslationUnit> PTUs;
103+
100104
unsigned InitPTUSize = 0;
101105

102106
// This member holds the last result of the value printing. It's a class
103107
// member because we might want to access it after more inputs. If no value
104108
// printing happens, it's in an invalid state.
105109
Value LastValue;
106110

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;
111+
// The cached declaration of std::string used as a return type for the built
112+
// trampoline. This is done in C++ to simplify the memory management for
113+
// user-defined printing functions.
114+
Decl *StdString = nullptr;
115+
116+
// A cache for the compiled destructors used to for de-allocation of managed
117+
// clang::Values.
118+
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
119+
120+
std::array<Expr *, 4> ValuePrintingInfo = {0};
121+
122+
/// When CodeGen is created the first llvm::Module gets cached in many places
123+
/// and we must keep it alive.
124+
std::unique_ptr<llvm::Module> CachedInCodeGenModule;
111125

112126
protected:
113127
// Derived classes can use an extended interface of the Interpreter.
114128
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err,
115-
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
129+
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
130+
std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);
116131

117132
// Create the internal IncrementalExecutor, or re-create it after calling
118133
// ResetExecutor().
@@ -122,15 +137,8 @@ class Interpreter {
122137
// JIT engine. In particular, it doesn't run cleanup or destructors.
123138
void ResetExecutor();
124139

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-
131140
public:
132141
virtual ~Interpreter();
133-
134142
static llvm::Expected<std::unique_ptr<Interpreter>>
135143
create(std::unique_ptr<CompilerInstance> CI);
136144
static llvm::Expected<std::unique_ptr<Interpreter>>
@@ -145,7 +153,6 @@ class Interpreter {
145153
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
146154
llvm::Error Execute(PartialTranslationUnit &T);
147155
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
148-
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
149156

150157
/// Undo N previous incremental inputs.
151158
llvm::Error Undo(unsigned N = 1);
@@ -167,23 +174,29 @@ class Interpreter {
167174
llvm::Expected<llvm::orc::ExecutorAddr>
168175
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
169176

170-
enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };
171-
172-
const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
173-
return ValuePrintingInfo;
174-
}
175-
176-
Expr *SynthesizeExpr(Expr *E);
177+
std::unique_ptr<llvm::Module> GenModule();
177178

178179
private:
179180
size_t getEffectivePTUSize() const;
180181
void markUserCodeStart();
181182

182-
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
183+
/// @}
184+
/// @name Value and pretty printing support
185+
/// @{
183186

184-
llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
187+
std::string ValueDataToString(const Value &V);
188+
std::string ValueTypeToString(const Value &V) const;
185189

186-
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
190+
llvm::Expected<Expr *> AttachValuePrinting(Expr *E);
191+
192+
// When we deallocate clang::Value we need to run the destructor of the type.
193+
// This function forces emission of the needed dtor.
194+
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
195+
196+
/// @}
197+
/// @name Code generation
198+
/// @{
199+
CodeGenerator *getCodeGen() const;
187200
};
188201
} // namespace clang
189202

clang/include/clang/Interpreter/Value.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ class raw_ostream;
4949
namespace clang {
5050

5151
class ASTContext;
52-
class Interpreter;
5352
class QualType;
5453

54+
class Interpreter;
55+
5556
#if defined(_WIN32)
5657
// REPL_EXTERNAL_VISIBILITY are symbols that we need to be able to locate
5758
// at runtime. On Windows, this requires them to be exported from any of the
@@ -118,9 +119,9 @@ class REPL_EXTERNAL_VISIBILITY Value {
118119
~Value();
119120

120121
void printType(llvm::raw_ostream &Out) const;
121-
void printData(llvm::raw_ostream &Out) const;
122-
void print(llvm::raw_ostream &Out) const;
123-
void dump() const;
122+
void printData(llvm::raw_ostream &Out);
123+
void print(llvm::raw_ostream &Out);
124+
void dump();
124125
void clear();
125126

126127
ASTContext &getASTContext();
@@ -138,6 +139,7 @@ class REPL_EXTERNAL_VISIBILITY Value {
138139
void setOpaqueType(void *Ty) { OpaqueType = Ty; }
139140

140141
void *getPtr() const;
142+
void **getPtrAddress() const;
141143
void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
142144

143145
#define X(type, name) \
@@ -204,6 +206,5 @@ template <> inline void *Value::as() const {
204206
return Data.m_Ptr;
205207
return (void *)as<uintptr_t>();
206208
}
207-
208209
} // namespace clang
209210
#endif

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/Headers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ set(core_files
3636
tgmath.h
3737
unwind.h
3838
varargs.h
39+
__clang_interpreter_runtime_printvalue.h
3940
)
4041

4142
set(arm_common_files

0 commit comments

Comments
 (0)