https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/83126
From 3a6fdd006f00b0530e7fe6ead1fcd2765c1bfe07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Mon, 26 Feb 2024 19:12:41 +0100 Subject: [PATCH 1/4] [clang-repl] Split out TypeVisitor from RuntimeInterfaceBuilder --- clang/lib/Interpreter/Interpreter.cpp | 171 ++++++++++++++------------ 1 file changed, 92 insertions(+), 79 deletions(-) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9f97a3c6b0be9e..7afe55bbb266a3 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -541,21 +541,104 @@ bool Interpreter::FindRuntimeInterface() { namespace { -class RuntimeInterfaceBuilder - : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> { - clang::Interpreter &Interp; +class InterfaceKindVisitor + : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> { + friend class RuntimeInterfaceBuilder; + ASTContext &Ctx; Sema &S; Expr *E; llvm::SmallVector<Expr *, 3> Args; +public: + InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E) + : Ctx(Ctx), S(S), E(E) {} + + Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { + return Interpreter::InterfaceKind::WithAlloc; + } + + Interpreter::InterfaceKind + VisitMemberPointerType(const MemberPointerType *Ty) { + return Interpreter::InterfaceKind::WithAlloc; + } + + Interpreter::InterfaceKind + VisitConstantArrayType(const ConstantArrayType *Ty) { + return Interpreter::InterfaceKind::CopyArray; + } + + Interpreter::InterfaceKind + VisitFunctionProtoType(const FunctionProtoType *Ty) { + HandlePtrType(Ty); + return Interpreter::InterfaceKind::NoAlloc; + } + + Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) { + HandlePtrType(Ty); + return Interpreter::InterfaceKind::NoAlloc; + } + + Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) { + ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); + assert(!AddrOfE.isInvalid() && "Can not create unary expression"); + Args.push_back(AddrOfE.get()); + return Interpreter::InterfaceKind::NoAlloc; + } + + Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { + if (Ty->isNullPtrType()) + Args.push_back(E); + else if (Ty->isFloatingType()) + Args.push_back(E); + else if (Ty->isIntegralOrEnumerationType()) + HandleIntegralOrEnumType(Ty); + else if (Ty->isVoidType()) { + // Do we need to still run `E`? + } + + return Interpreter::InterfaceKind::NoAlloc; + } + + Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) { + HandleIntegralOrEnumType(Ty); + return Interpreter::InterfaceKind::NoAlloc; + } + +private: + // Force cast these types to uint64 to reduce the number of overloads of + // `__clang_Interpreter_SetValueNoAlloc`. + void HandleIntegralOrEnumType(const Type *Ty) { + TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy); + ExprResult CastedExpr = + S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); + assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); + Args.push_back(CastedExpr.get()); + } + + void HandlePtrType(const Type *Ty) { + TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); + ExprResult CastedExpr = + S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); + assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); + Args.push_back(CastedExpr.get()); + } +}; + +class RuntimeInterfaceBuilder { + clang::Interpreter &Interp; + ASTContext &Ctx; + Sema &S; + Expr *E; + InterfaceKindVisitor Visitor; + public: RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef, Expr *VE, ArrayRef<Expr *> FixedArgs) - : Interp(In), Ctx(C), S(SemaRef), E(VE) { + : Interp(In), Ctx(C), S(SemaRef), E(VE), Visitor(C, SemaRef, VE) { // The Interpreter* parameter and the out parameter `OutVal`. for (Expr *E : FixedArgs) - Args.push_back(E); + Visitor.Args.push_back(E); // Get rid of ExprWithCleanups. if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) @@ -575,11 +658,11 @@ class RuntimeInterfaceBuilder Expr *TypeArg = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); // The QualType parameter `OpaqueType`, represented as `void*`. - Args.push_back(TypeArg); + Visitor.Args.push_back(TypeArg); // We push the last parameter based on the type of the Expr. Note we need // special care for rvalue struct. - Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy); + Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy); switch (Kind) { case Interpreter::InterfaceKind::WithAlloc: case Interpreter::InterfaceKind::CopyArray: { @@ -587,7 +670,7 @@ class RuntimeInterfaceBuilder ExprResult AllocCall = S.ActOnCallExpr( /*Scope=*/nullptr, Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], - E->getBeginLoc(), Args, E->getEndLoc()); + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); @@ -634,82 +717,12 @@ class RuntimeInterfaceBuilder return S.ActOnCallExpr( /*Scope=*/nullptr, Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], - E->getBeginLoc(), Args, E->getEndLoc()); + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); } default: llvm_unreachable("Unhandled Interpreter::InterfaceKind"); } } - - Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { - return Interpreter::InterfaceKind::WithAlloc; - } - - Interpreter::InterfaceKind - VisitMemberPointerType(const MemberPointerType *Ty) { - return Interpreter::InterfaceKind::WithAlloc; - } - - Interpreter::InterfaceKind - VisitConstantArrayType(const ConstantArrayType *Ty) { - return Interpreter::InterfaceKind::CopyArray; - } - - Interpreter::InterfaceKind - VisitFunctionProtoType(const FunctionProtoType *Ty) { - HandlePtrType(Ty); - return Interpreter::InterfaceKind::NoAlloc; - } - - Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) { - HandlePtrType(Ty); - return Interpreter::InterfaceKind::NoAlloc; - } - - Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) { - ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); - assert(!AddrOfE.isInvalid() && "Can not create unary expression"); - Args.push_back(AddrOfE.get()); - return Interpreter::InterfaceKind::NoAlloc; - } - - Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { - if (Ty->isNullPtrType()) - Args.push_back(E); - else if (Ty->isFloatingType()) - Args.push_back(E); - else if (Ty->isIntegralOrEnumerationType()) - HandleIntegralOrEnumType(Ty); - else if (Ty->isVoidType()) { - // Do we need to still run `E`? - } - - return Interpreter::InterfaceKind::NoAlloc; - } - - Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) { - HandleIntegralOrEnumType(Ty); - return Interpreter::InterfaceKind::NoAlloc; - } - -private: - // Force cast these types to uint64 to reduce the number of overloads of - // `__clang_Interpreter_SetValueNoAlloc`. - void HandleIntegralOrEnumType(const Type *Ty) { - TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy); - ExprResult CastedExpr = - S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); - assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); - Args.push_back(CastedExpr.get()); - } - - void HandlePtrType(const Type *Ty) { - TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); - ExprResult CastedExpr = - S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); - assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); - Args.push_back(CastedExpr.get()); - } }; } // namespace From 78bea3a4ec2401c3043bff86aeb7a136f280f5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Mon, 26 Feb 2024 19:26:14 +0100 Subject: [PATCH 2/4] [clang-repl] Construct RuntimeInterfaceBuilder early and pass invocation-specific params in getCall() --- clang/lib/Interpreter/Interpreter.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7afe55bbb266a3..f0b9195b684ba6 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -629,23 +629,22 @@ class RuntimeInterfaceBuilder { clang::Interpreter &Interp; ASTContext &Ctx; Sema &S; - Expr *E; - InterfaceKindVisitor Visitor; public: - RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef, - Expr *VE, ArrayRef<Expr *> FixedArgs) - : Interp(In), Ctx(C), S(SemaRef), E(VE), Visitor(C, SemaRef, VE) { - // The Interpreter* parameter and the out parameter `OutVal`. - for (Expr *E : FixedArgs) - Visitor.Args.push_back(E); + RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef) + : Interp(In), Ctx(C), S(SemaRef) {} + ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) { // Get rid of ExprWithCleanups. if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) E = EWC->getSubExpr(); - } - ExprResult getCall() { + InterfaceKindVisitor Visitor(Ctx, S, E); + + // The Interpreter* parameter and the out parameter `OutVal`. + for (Expr *E : FixedArgs) + Visitor.Args.push_back(E); + QualType Ty = E->getType(); QualType DesugaredTy = Ty.getDesugaredType(Ctx); @@ -747,6 +746,8 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { if (!FindRuntimeInterface()) llvm_unreachable("We can't find the runtime iterface for pretty print!"); + RuntimeInterfaceBuilder Builder(*this, Ctx, S); + // Create parameter `ThisInterp`. auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); @@ -754,9 +755,8 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); // Build `__clang_Interpreter_SetValue*` call. - RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue}); + ExprResult Result = Builder.getCall(E, {ThisInterp, OutValue}); - ExprResult Result = Builder.getCall(); // It could fail, like printing an array type in C. (not supported) if (Result.isInvalid()) return E; From 0f9469987aefdf1a76da27a2352da80de7a5561b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Mon, 26 Feb 2024 20:04:17 +0100 Subject: [PATCH 3/4] [clang-repl] Let FindRuntimeInterface() return RuntimeInterfaceBuilder and make it virtual --- clang/include/clang/Interpreter/Interpreter.h | 22 +++++-- clang/lib/Interpreter/Interpreter.cpp | 58 +++++++++++++------ 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 292fa566ae7037..787357ea7f20c3 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -18,6 +18,7 @@ #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" @@ -72,17 +73,22 @@ class IncrementalCompilerBuilder { llvm::StringRef CudaSDKPath; }; +class RuntimeInterfaceBuilder { +public: + virtual ~RuntimeInterfaceBuilder() = default; + virtual ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) = 0; +}; + /// Provides top-level interfaces for incremental compilation and execution. class Interpreter { std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx; 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; - Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err); - llvm::Error CreateExecutor(); unsigned InitPTUSize = 0; @@ -91,8 +97,13 @@ class Interpreter { // printing happens, it's in an invalid state. Value LastValue; +protected: + Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err); + + void finalizeInitPTUStack(); + public: - ~Interpreter(); + virtual ~Interpreter(); static llvm::Expected<std::unique_ptr<Interpreter>> create(std::unique_ptr<CompilerInstance> CI); static llvm::Expected<std::unique_ptr<Interpreter>> @@ -137,11 +148,12 @@ class Interpreter { Expr *SynthesizeExpr(Expr *E); +protected: + virtual RuntimeInterfaceBuilder *FindRuntimeInterface(); + private: size_t getEffectivePTUSize() const; - bool FindRuntimeInterface(); - llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors; llvm::SmallVector<Expr *, 4> ValuePrintingInfo; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index f0b9195b684ba6..4dc15f5c735fc3 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -283,10 +283,12 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI) { return PTU.takeError(); Interp->ValuePrintingInfo.resize(4); + // FIXME: This is a ugly hack. Undo command checks its availability by looking // at the size of the PTU list. However we have parsed something in the // beginning of the REPL so we have to mark them as 'Irrevocable'. - Interp->InitPTUSize = Interp->IncrParser->getPTUs().size(); + Interp->finalizeInitPTUStack(); + return std::move(Interp); } @@ -343,6 +345,11 @@ const ASTContext &Interpreter::getASTContext() const { return getCompilerInstance()->getASTContext(); } +void Interpreter::finalizeInitPTUStack() { + assert(!InitPTUSize && "We only do this once"); + InitPTUSize = IncrParser->getPTUs().size(); +} + size_t Interpreter::getEffectivePTUSize() const { std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); @@ -505,9 +512,16 @@ static constexpr llvm::StringRef MagicRuntimeInterface[] = { "__clang_Interpreter_SetValueWithAlloc", "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; -bool Interpreter::FindRuntimeInterface() { +static std::unique_ptr<RuntimeInterfaceBuilder> +createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, + Sema &S); + +RuntimeInterfaceBuilder *Interpreter::FindRuntimeInterface() { + if (RuntimeIB) + return RuntimeIB.get(); + if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) - return true; + return nullptr; Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); @@ -526,24 +540,26 @@ bool Interpreter::FindRuntimeInterface() { if (!LookupInterface(ValuePrintingInfo[NoAlloc], MagicRuntimeInterface[NoAlloc])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[WithAlloc], MagicRuntimeInterface[WithAlloc])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[CopyArray], MagicRuntimeInterface[CopyArray])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[NewTag], MagicRuntimeInterface[NewTag])) - return false; - return true; + return nullptr; + + RuntimeIB = createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); + return RuntimeIB.get(); } namespace { class InterfaceKindVisitor : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> { - friend class RuntimeInterfaceBuilder; + friend class InProcessRuntimeInterfaceBuilder; ASTContext &Ctx; Sema &S; @@ -625,16 +641,16 @@ class InterfaceKindVisitor } }; -class RuntimeInterfaceBuilder { - clang::Interpreter &Interp; +class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { + Interpreter &Interp; ASTContext &Ctx; Sema &S; public: - RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef) - : Interp(In), Ctx(C), S(SemaRef) {} + InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S) + : Interp(Interp), Ctx(C), S(S) {} - ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) { + ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) override { // Get rid of ExprWithCleanups. if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) E = EWC->getSubExpr(); @@ -725,6 +741,12 @@ class RuntimeInterfaceBuilder { }; } // namespace +static std::unique_ptr<RuntimeInterfaceBuilder> +createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, + Sema &S) { + return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S); +} + // This synthesizes a call expression to a speciall // function that is responsible for generating the Value. // In general, we transform: @@ -743,10 +765,8 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); - if (!FindRuntimeInterface()) - llvm_unreachable("We can't find the runtime iterface for pretty print!"); - - RuntimeInterfaceBuilder Builder(*this, Ctx, S); + RuntimeInterfaceBuilder *Builder = FindRuntimeInterface(); + assert(Builder && "We can't find the runtime interface for pretty print!"); // Create parameter `ThisInterp`. auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); @@ -755,7 +775,7 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); // Build `__clang_Interpreter_SetValue*` call. - ExprResult Result = Builder.getCall(E, {ThisInterp, OutValue}); + ExprResult Result = Builder->getCall(E, {ThisInterp, OutValue}); // It could fail, like printing an array type in C. (not supported) if (Result.isInvalid()) From f069bafd8a3c597934f17236b530ffbcfe8d0f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Wed, 28 Feb 2024 11:13:48 +0100 Subject: [PATCH 4/4] [clang-repl] Avoid virtual function calls in RuntimeInterfaceBuilder abstraction --- clang/include/clang/Interpreter/Interpreter.h | 8 +- clang/lib/Interpreter/Interpreter.cpp | 180 +++++++++--------- 2 files changed, 98 insertions(+), 90 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 787357ea7f20c3..0aae00ddd216f7 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -76,7 +76,9 @@ class IncrementalCompilerBuilder { class RuntimeInterfaceBuilder { public: virtual ~RuntimeInterfaceBuilder() = default; - virtual ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) = 0; + + using AddCallToRuntimeInterfaceFunction = ExprResult(RuntimeInterfaceBuilder *Builder, Expr *, ArrayRef<Expr *>); + virtual AddCallToRuntimeInterfaceFunction *getCallCallback() = 0; }; /// Provides top-level interfaces for incremental compilation and execution. @@ -100,6 +102,8 @@ class Interpreter { protected: Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err); + RuntimeInterfaceBuilder::AddCallToRuntimeInterfaceFunction* AddCallToRuntimeInterface = nullptr; + void finalizeInitPTUStack(); public: @@ -149,7 +153,7 @@ class Interpreter { Expr *SynthesizeExpr(Expr *E); protected: - virtual RuntimeInterfaceBuilder *FindRuntimeInterface(); + virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface(); private: size_t getEffectivePTUSize() const; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 4dc15f5c735fc3..a1c577bd2863b1 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -516,10 +516,7 @@ static std::unique_ptr<RuntimeInterfaceBuilder> createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, Sema &S); -RuntimeInterfaceBuilder *Interpreter::FindRuntimeInterface() { - if (RuntimeIB) - return RuntimeIB.get(); - +std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() { if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) return nullptr; @@ -551,8 +548,7 @@ RuntimeInterfaceBuilder *Interpreter::FindRuntimeInterface() { MagicRuntimeInterface[NewTag])) return nullptr; - RuntimeIB = createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); - return RuntimeIB.get(); + return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); } namespace { @@ -650,93 +646,97 @@ class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S) : Interp(Interp), Ctx(C), S(S) {} - ExprResult getCall(Expr *E, ArrayRef<Expr *> FixedArgs) override { - // Get rid of ExprWithCleanups. - if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) - E = EWC->getSubExpr(); + AddCallToRuntimeInterfaceFunction *getCallCallback() override { + return [](RuntimeInterfaceBuilder *Builder, Expr *E, ArrayRef<Expr *> FixedArgs) -> ExprResult { + auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder); - InterfaceKindVisitor Visitor(Ctx, S, E); + // Get rid of ExprWithCleanups. + if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) + E = EWC->getSubExpr(); - // The Interpreter* parameter and the out parameter `OutVal`. - for (Expr *E : FixedArgs) - Visitor.Args.push_back(E); + InterfaceKindVisitor Visitor(B->Ctx, B->S, E); - QualType Ty = E->getType(); - QualType DesugaredTy = Ty.getDesugaredType(Ctx); + // The Interpreter* parameter and the out parameter `OutVal`. + for (Expr *E : FixedArgs) + Visitor.Args.push_back(E); - // For lvalue struct, we treat it as a reference. - if (DesugaredTy->isRecordType() && E->isLValue()) { - DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy); - Ty = Ctx.getLValueReferenceType(Ty); - } + QualType Ty = E->getType(); + QualType DesugaredTy = Ty.getDesugaredType(B->Ctx); - Expr *TypeArg = - CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); - // The QualType parameter `OpaqueType`, represented as `void*`. - Visitor.Args.push_back(TypeArg); - - // We push the last parameter based on the type of the Expr. Note we need - // special care for rvalue struct. - Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy); - switch (Kind) { - case Interpreter::InterfaceKind::WithAlloc: - case Interpreter::InterfaceKind::CopyArray: { - // __clang_Interpreter_SetValueWithAlloc. - ExprResult AllocCall = S.ActOnCallExpr( - /*Scope=*/nullptr, - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], - E->getBeginLoc(), Visitor.Args, E->getEndLoc()); - assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); - - TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); - - // Force CodeGen to emit destructor. - if (auto *RD = Ty->getAsCXXRecordDecl()) { - auto *Dtor = S.LookupDestructor(RD); - Dtor->addAttr(UsedAttr::CreateImplicit(Ctx)); - Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( - DeclGroupRef(Dtor)); + // For lvalue struct, we treat it as a reference. + if (DesugaredTy->isRecordType() && E->isLValue()) { + DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy); + Ty = B->Ctx.getLValueReferenceType(Ty); } - // __clang_Interpreter_SetValueCopyArr. - if (Kind == Interpreter::InterfaceKind::CopyArray) { - const auto *ConstantArrTy = - cast<ConstantArrayType>(DesugaredTy.getTypePtr()); - size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); - Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); - Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; - return S.ActOnCallExpr( - /*Scope *=*/nullptr, - Interp - .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], - SourceLocation(), Args, SourceLocation()); + Expr *TypeArg = + CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); + // The QualType parameter `OpaqueType`, represented as `void*`. + Visitor.Args.push_back(TypeArg); + + // We push the last parameter based on the type of the Expr. Note we need + // special care for rvalue struct. + Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy); + switch (Kind) { + case Interpreter::InterfaceKind::WithAlloc: + case Interpreter::InterfaceKind::CopyArray: { + // __clang_Interpreter_SetValueWithAlloc. + ExprResult AllocCall = B->S.ActOnCallExpr( + /*Scope=*/nullptr, + B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); + assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); + + TypeSourceInfo *TSI = B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); + + // Force CodeGen to emit destructor. + if (auto *RD = Ty->getAsCXXRecordDecl()) { + auto *Dtor = B->S.LookupDestructor(RD); + Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx)); + B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( + DeclGroupRef(Dtor)); + } + + // __clang_Interpreter_SetValueCopyArr. + if (Kind == Interpreter::InterfaceKind::CopyArray) { + const auto *ConstantArrTy = + cast<ConstantArrayType>(DesugaredTy.getTypePtr()); + size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy); + Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize); + Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; + return B->S.ActOnCallExpr( + /*Scope *=*/nullptr, + B->Interp + .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], + SourceLocation(), Args, SourceLocation()); + } + Expr *Args[] = { + AllocCall.get(), + B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; + ExprResult CXXNewCall = B->S.BuildCXXNew( + E->getSourceRange(), + /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, + /*PlacementRParen=*/SourceLocation(), + /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, + E->getSourceRange(), E); + + assert(!CXXNewCall.isInvalid() && + "Can't create runtime placement new call!"); + + return B->S.ActOnFinishFullExpr(CXXNewCall.get(), + /*DiscardedValue=*/false); } - Expr *Args[] = { - AllocCall.get(), - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; - ExprResult CXXNewCall = S.BuildCXXNew( - E->getSourceRange(), - /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, - /*PlacementRParen=*/SourceLocation(), - /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, - E->getSourceRange(), E); - - assert(!CXXNewCall.isInvalid() && - "Can't create runtime placement new call!"); - - return S.ActOnFinishFullExpr(CXXNewCall.get(), - /*DiscardedValue=*/false); - } - // __clang_Interpreter_SetValueNoAlloc. - case Interpreter::InterfaceKind::NoAlloc: { - return S.ActOnCallExpr( - /*Scope=*/nullptr, - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], - E->getBeginLoc(), Visitor.Args, E->getEndLoc()); - } - default: - llvm_unreachable("Unhandled Interpreter::InterfaceKind"); - } + // __clang_Interpreter_SetValueNoAlloc. + case Interpreter::InterfaceKind::NoAlloc: { + return B->S.ActOnCallExpr( + /*Scope=*/nullptr, + B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); + } + default: + llvm_unreachable("Unhandled Interpreter::InterfaceKind"); + } + }; } }; } // namespace @@ -765,8 +765,12 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); - RuntimeInterfaceBuilder *Builder = FindRuntimeInterface(); - assert(Builder && "We can't find the runtime interface for pretty print!"); + if (!RuntimeIB) { + RuntimeIB = FindRuntimeInterface(); + AddCallToRuntimeInterface = RuntimeIB->getCallCallback(); + } + + assert(AddCallToRuntimeInterface && "We don't have a runtime interface for pretty print!"); // Create parameter `ThisInterp`. auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); @@ -775,7 +779,7 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); // Build `__clang_Interpreter_SetValue*` call. - ExprResult Result = Builder->getCall(E, {ThisInterp, OutValue}); + ExprResult Result = AddCallToRuntimeInterface(RuntimeIB.get(), E, {ThisInterp, OutValue}); // It could fail, like printing an array type in C. (not supported) if (Result.isInvalid()) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits