Skip to content

Commit 456b66b

Browse files
committed
[clang-repl] Reimplement value printing using MemoryAccess to support in-process and out-of-process
1 parent d8c8c67 commit 456b66b

File tree

7 files changed

+654
-269
lines changed

7 files changed

+654
-269
lines changed

clang/include/clang/Interpreter/Interpreter.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,7 @@ class Interpreter {
109109

110110
unsigned InitPTUSize = 0;
111111

112-
// This member holds the last result of the value printing. It's a class
113-
// member because we might want to access it after more inputs. If no value
114-
// printing happens, it's in an invalid state.
115-
Value LastValue;
112+
std::unique_ptr<ValueResultManager> ValMgr;
116113

117114
/// Compiler instance performing the incremental compilation.
118115
std::unique_ptr<CompilerInstance> CI;
@@ -185,7 +182,7 @@ class Interpreter {
185182

186183
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
187184
llvm::Error Execute(PartialTranslationUnit &T);
188-
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
185+
llvm::Error ParseAndExecute(llvm::StringRef Code);
189186

190187
/// Undo N previous incremental inputs.
191188
llvm::Error Undo(unsigned N = 1);
@@ -226,9 +223,8 @@ class Interpreter {
226223
/// @{
227224

228225
std::string ValueDataToString(const Value &V) const;
229-
std::string ValueTypeToString(const Value &V) const;
230226

231-
llvm::Expected<Expr *> convertExprToValue(Expr *E);
227+
llvm::Expected<Expr *> convertExprToValue(Expr *E, bool IsOOP = true);
232228

233229
// When we deallocate clang::Value we need to run the destructor of the type.
234230
// This function forces emission of the needed dtor.

clang/include/clang/Interpreter/Value.h

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@
3232

3333
#ifndef LLVM_CLANG_INTERPRETER_VALUE_H
3434
#define LLVM_CLANG_INTERPRETER_VALUE_H
35-
35+
#include "llvm/ADT/FunctionExtras.h"
3636
#include "llvm/Config/llvm-config.h" // for LLVM_BUILD_LLVM_DYLIB, LLVM_BUILD_SHARED_LIBS
37+
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
38+
#include "llvm/ExecutionEngine/Orc/MemoryAccess.h"
39+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
3740
#include "llvm/Support/Compiler.h"
3841
#include <cassert>
3942
#include <cstdint>
@@ -107,7 +110,7 @@ class REPL_EXTERNAL_VISIBILITY Value {
107110
REPL_BUILTIN_TYPES
108111
#undef X
109112

110-
K_Void,
113+
K_Void,
111114
K_PtrOrObj,
112115
K_Unspecified
113116
};
@@ -206,5 +209,48 @@ template <> inline void *Value::as() const {
206209
return Data.m_Ptr;
207210
return (void *)as<uintptr_t>();
208211
}
212+
213+
class ValueBuffer {
214+
public:
215+
QualType Ty;
216+
virtual ~ValueBuffer() = default;
217+
virtual std::string toString() const = 0;
218+
virtual bool isValid() const = 0;
219+
};
220+
221+
class ValueResultManager {
222+
public:
223+
using ValueId = uint64_t;
224+
using SendResultFn = llvm::unique_function<void(llvm::Error)>;
225+
226+
explicit ValueResultManager(ASTContext &Ctx, llvm::orc::MemoryAccess &MemAcc);
227+
228+
static std::unique_ptr<ValueResultManager>
229+
Create(llvm::orc::LLJIT &EE, ASTContext &Ctx, bool IsOutOfProcess = true);
230+
231+
ValueId registerPendingResult(QualType QT) {
232+
ValueId NewID = NextID.fetch_add(1, std::memory_order_relaxed);
233+
IdToType.insert({NewID, QT});
234+
return NewID;
235+
}
236+
237+
void resetAndDump();
238+
239+
void deliverResult(SendResultFn SendResult, ValueId ID,
240+
llvm::orc::ExecutorAddr VAddr);
241+
242+
private:
243+
std::atomic<ValueId> NextID{1};
244+
void Initialize(llvm::orc::LLJIT &EE);
245+
246+
std::string ValueTypeToString(QualType QT) const;
247+
248+
mutable std::mutex Mutex;
249+
ASTContext &Ctx;
250+
llvm::orc::MemoryAccess &MemAcc;
251+
std::unique_ptr<ValueBuffer> ValBuf = nullptr;
252+
llvm::DenseMap<ValueId, clang::QualType> IdToType;
253+
};
254+
209255
} // namespace clang
210256
#endif

clang/lib/Interpreter/Interpreter.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
302302
return;
303303
}
304304
}
305+
306+
ValMgr = ValueResultManager::Create(IncrExecutor->GetExecutionEngine(),
307+
getASTContext());
305308
}
306309

307310
Interpreter::~Interpreter() {
@@ -324,6 +327,7 @@ Interpreter::~Interpreter() {
324327
// code them.
325328
const char *const Runtimes = R"(
326329
#define __CLANG_REPL__ 1
330+
327331
#ifdef __cplusplus
328332
#define EXTERN_C extern "C"
329333
struct __clang_Interpreter_NewTag{} __ci_newtag;
@@ -344,6 +348,8 @@ const char *const Runtimes = R"(
344348
memcpy(Placement, Src, Size);
345349
}
346350
#endif // __cplusplus
351+
EXTERN_C void __clang_Interpreter_SendResultValue(void *Ctx, unsigned long long, void*);
352+
EXTERN_C void __orc_rt_SendResultValue(unsigned long long, void*);
347353
EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
348354
EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
349355
)";
@@ -699,7 +705,7 @@ llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
699705
return llvm::Error::success();
700706
}
701707

702-
llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
708+
llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code) {
703709

704710
auto PTU = Parse(Code);
705711
if (!PTU)
@@ -708,12 +714,8 @@ llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
708714
if (llvm::Error Err = Execute(*PTU))
709715
return Err;
710716

711-
if (LastValue.isValid()) {
712-
if (!V) {
713-
LastValue.dump();
714-
LastValue.clear();
715-
} else
716-
*V = std::move(LastValue);
717+
if (ValMgr) {
718+
ValMgr->resetAndDump();
717719
}
718720
return llvm::Error::success();
719721
}

0 commit comments

Comments
 (0)