Skip to content

[clang-repl] Simplify the value printing logic to enable out-of-process. #107737

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 5 commits into from
Sep 23, 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
3 changes: 2 additions & 1 deletion clang/include/clang/Frontend/MultiplexConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class MultiplexConsumer : public SemaConsumer {
public:
// Takes ownership of the pointers in C.
MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>> C);
MultiplexConsumer(std::unique_ptr<ASTConsumer> C);
~MultiplexConsumer() override;

// ASTConsumer
Expand Down Expand Up @@ -80,7 +81,7 @@ class MultiplexConsumer : public SemaConsumer {
void InitializeSema(Sema &S) override;
void ForgetSema() override;

private:
protected:
std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these.
std::unique_ptr<MultiplexASTMutationListener> MutationListener;
std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener;
Expand Down
58 changes: 30 additions & 28 deletions clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
#ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
#define LLVM_CLANG_INTERPRETER_INTERPRETER_H

#include "clang/AST/Decl.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Interpreter/Value.h"
#include "clang/Sema/Ownership.h"

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

class CompilerInstance;
class CodeGenerator;
class CXXRecordDecl;
class Decl;
class IncrementalExecutor;
class IncrementalParser;

Expand Down Expand Up @@ -77,42 +78,45 @@ class IncrementalCompilerBuilder {
llvm::StringRef CudaSDKPath;
};

/// Generate glue code between the Interpreter's built-in runtime and user code.
class RuntimeInterfaceBuilder {
public:
virtual ~RuntimeInterfaceBuilder() = default;

using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder,
Expr *, ArrayRef<Expr *>);
virtual TransformExprFunction *getPrintValueTransformer() = 0;
};
class IncrementalAction;
class InProcessPrintingASTConsumer;

/// Provides top-level interfaces for incremental compilation and execution.
class Interpreter {
friend class Value;
friend InProcessPrintingASTConsumer;

std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx;
/// Long-lived, incremental parsing action.
std::unique_ptr<IncrementalAction> Act;
std::unique_ptr<IncrementalParser> IncrParser;
std::unique_ptr<IncrementalExecutor> IncrExecutor;
std::unique_ptr<RuntimeInterfaceBuilder> RuntimeIB;

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

/// List containing information about each incrementally parsed piece of code.
std::list<PartialTranslationUnit> PTUs;

unsigned InitPTUSize = 0;

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

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

/// Compiler instance performing the incremental compilation.
std::unique_ptr<CompilerInstance> CI;

protected:
// Derived classes can use an extended interface of the Interpreter.
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);

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

// Lazily construct the RuntimeInterfaceBuilder. The provided instance will be
// used for the entire lifetime of the interpreter. The default implementation
// targets the in-process __clang_Interpreter runtime. Override this to use a
// custom runtime.
virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface();

public:
virtual ~Interpreter();

static llvm::Expected<std::unique_ptr<Interpreter>>
create(std::unique_ptr<CompilerInstance> CI);
static llvm::Expected<std::unique_ptr<Interpreter>>
Expand All @@ -145,7 +142,6 @@ class Interpreter {
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
llvm::Error Execute(PartialTranslationUnit &T);
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);

/// Undo N previous incremental inputs.
llvm::Error Undo(unsigned N = 1);
Expand All @@ -167,8 +163,6 @@ class Interpreter {
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;

enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };

const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
return ValuePrintingInfo;
}
Expand All @@ -178,7 +172,15 @@ class Interpreter {
private:
size_t getEffectivePTUSize() const;
void markUserCodeStart();
llvm::Expected<Expr *> ExtractValueFromExpr(Expr *E);
llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);

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

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

llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Frontend/MultiplexConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ MultiplexConsumer::MultiplexConsumer(
}
}

MultiplexConsumer::MultiplexConsumer(std::unique_ptr<ASTConsumer> C)
: MultiplexConsumer([](std::unique_ptr<ASTConsumer> Consumer) {
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(std::move(Consumer));
return Consumers;
}(std::move(C))) {}

MultiplexConsumer::~MultiplexConsumer() {}

void MultiplexConsumer::Initialize(ASTContext &Context) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_clang_library(clangInterpreter
IncrementalExecutor.cpp
IncrementalParser.cpp
Interpreter.cpp
InterpreterValuePrinter.cpp
InterpreterUtils.cpp
Value.cpp
${WASM_SRC}
Expand Down
21 changes: 12 additions & 9 deletions clang/lib/Interpreter/DeviceOffload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Interpreter/PartialTranslationUnit.h"

#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
Expand All @@ -24,15 +25,17 @@
namespace clang {

IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
Interpreter &Interp, std::unique_ptr<CompilerInstance> Instance,
IncrementalParser &HostParser, llvm::LLVMContext &LLVMCtx,
std::unique_ptr<CompilerInstance> DeviceInstance,
CompilerInstance &HostInstance,
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
llvm::Error &Err)
: IncrementalParser(Interp, std::move(Instance), LLVMCtx, Err),
HostParser(HostParser), VFS(FS) {
llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
: IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
CodeGenOpts(HostInstance.getCodeGenOpts()),
TargetOpts(HostInstance.getTargetOpts()) {
if (Err)
return;
StringRef Arch = CI->getTargetOpts().CPU;
DeviceCI = std::move(DeviceInstance);
StringRef Arch = TargetOpts.CPU;
if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(
"Invalid CUDA architecture",
Expand All @@ -41,7 +44,7 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
}
}

llvm::Expected<PartialTranslationUnit &>
llvm::Expected<TranslationUnitDecl *>
IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
auto PTU = IncrementalParser::Parse(Input);
if (!PTU)
Expand All @@ -62,7 +65,7 @@ IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
llvm::StringRef(FatbinContent.data(), FatbinContent.size()),
"", false));

HostParser.getCI()->getCodeGenOpts().CudaGpuBinaryFileName = FatbinFileName;
CodeGenOpts.CudaGpuBinaryFileName = FatbinFileName;

FatbinContent.clear();

Expand All @@ -80,7 +83,7 @@ llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() {
std::error_code());
llvm::TargetOptions TO = llvm::TargetOptions();
llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
PTU.TheModule->getTargetTriple(), getCI()->getTargetOpts().CPU, "", TO,
PTU.TheModule->getTargetTriple(), TargetOpts.CPU, "", TO,
llvm::Reloc::Model::PIC_);
PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());

Expand Down
21 changes: 14 additions & 7 deletions clang/lib/Interpreter/DeviceOffload.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,24 @@
#include "llvm/Support/VirtualFileSystem.h"

namespace clang {
struct PartialTranslationUnit;
class CompilerInstance;
class CodeGenOptions;
class TargetOptions;

class IncrementalCUDADeviceParser : public IncrementalParser {
const std::list<PartialTranslationUnit> &PTUs;

public:
IncrementalCUDADeviceParser(
Interpreter &Interp, std::unique_ptr<CompilerInstance> Instance,
IncrementalParser &HostParser, llvm::LLVMContext &LLVMCtx,
std::unique_ptr<CompilerInstance> DeviceInstance,
CompilerInstance &HostInstance,
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS,
llvm::Error &Err);
llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs);

llvm::Expected<PartialTranslationUnit &>
Parse(llvm::StringRef Input) override;
llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override;

// Generate PTX for the last PTU
// Generate PTX for the last PTU.
llvm::Expected<llvm::StringRef> GeneratePTX();

// Generate fatbinary contents in memory
Expand All @@ -39,11 +44,13 @@ class IncrementalCUDADeviceParser : public IncrementalParser {
~IncrementalCUDADeviceParser();

protected:
IncrementalParser &HostParser;
std::unique_ptr<CompilerInstance> DeviceCI;
int SMVersion;
llvm::SmallString<1024> PTXCode;
llvm::SmallVector<char, 1024> FatbinContent;
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
CodeGenOptions &CodeGenOpts; // Intentionally a reference.
const TargetOptions &TargetOpts;
};

} // namespace clang
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Interpreter/IncrementalExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
return SymOrErr->getAddress();
}

} // end namespace clang
} // namespace clang
Loading
Loading