[clang] [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (PR #83683)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 15 01:49:44 PDT 2024
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>,
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/83683 at github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/83683
>From 8440f6bb5f16dd33f5227ce942b160997be0a36f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 2 Mar 2024 17:00:26 +0100
Subject: [PATCH 1/3] [clang][Interp] Merge ByteCode{Stmt,Expr}Gen
---
clang/lib/AST/CMakeLists.txt | 1 -
clang/lib/AST/Interp/ByteCodeExprGen.cpp | 701 +++++++++++++++++++++-
clang/lib/AST/Interp/ByteCodeExprGen.h | 48 +-
clang/lib/AST/Interp/ByteCodeStmtGen.cpp | 731 -----------------------
clang/lib/AST/Interp/ByteCodeStmtGen.h | 91 ---
clang/lib/AST/Interp/Context.cpp | 5 +-
clang/lib/AST/Interp/EvalEmitter.h | 1 +
clang/lib/AST/Interp/Program.cpp | 1 -
8 files changed, 748 insertions(+), 831 deletions(-)
delete mode 100644 clang/lib/AST/Interp/ByteCodeStmtGen.cpp
delete mode 100644 clang/lib/AST/Interp/ByteCodeStmtGen.h
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index a5d3dacfc1a84..c5196fbf7ef74 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -66,7 +66,6 @@ add_clang_library(clangAST
InheritViz.cpp
Interp/ByteCodeEmitter.cpp
Interp/ByteCodeExprGen.cpp
- Interp/ByteCodeStmtGen.cpp
Interp/Context.cpp
Interp/Descriptor.cpp
Interp/Disasm.cpp
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 300c013d15da8..3e06e25c02559 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -8,7 +8,6 @@
#include "ByteCodeExprGen.h"
#include "ByteCodeEmitter.h"
-#include "ByteCodeStmtGen.h"
#include "Context.h"
#include "Floating.h"
#include "Function.h"
@@ -72,6 +71,70 @@ template <class Emitter> class OptionScope final {
bool OldInitializing;
};
+/// Scope managing label targets.
+template <class Emitter> class LabelScope {
+public:
+ virtual ~LabelScope() {}
+
+protected:
+ LabelScope(ByteCodeExprGen<Emitter> *Ctx) : Ctx(Ctx) {}
+ /// ByteCodeExprGen instance.
+ ByteCodeExprGen<Emitter> *Ctx;
+};
+
+/// Sets the context for break/continue statements.
+template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
+public:
+ using LabelTy = typename ByteCodeExprGen<Emitter>::LabelTy;
+ using OptLabelTy = typename ByteCodeExprGen<Emitter>::OptLabelTy;
+
+ LoopScope(ByteCodeExprGen<Emitter> *Ctx, LabelTy BreakLabel,
+ LabelTy ContinueLabel)
+ : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
+ OldContinueLabel(Ctx->ContinueLabel) {
+ this->Ctx->BreakLabel = BreakLabel;
+ this->Ctx->ContinueLabel = ContinueLabel;
+ }
+
+ ~LoopScope() {
+ this->Ctx->BreakLabel = OldBreakLabel;
+ this->Ctx->ContinueLabel = OldContinueLabel;
+ }
+
+private:
+ OptLabelTy OldBreakLabel;
+ OptLabelTy OldContinueLabel;
+};
+
+// Sets the context for a switch scope, mapping labels.
+template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
+public:
+ using LabelTy = typename ByteCodeExprGen<Emitter>::LabelTy;
+ using OptLabelTy = typename ByteCodeExprGen<Emitter>::OptLabelTy;
+ using CaseMap = typename ByteCodeExprGen<Emitter>::CaseMap;
+
+ SwitchScope(ByteCodeExprGen<Emitter> *Ctx, CaseMap &&CaseLabels,
+ LabelTy BreakLabel, OptLabelTy DefaultLabel)
+ : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
+ OldDefaultLabel(this->Ctx->DefaultLabel),
+ OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
+ this->Ctx->BreakLabel = BreakLabel;
+ this->Ctx->DefaultLabel = DefaultLabel;
+ this->Ctx->CaseLabels = std::move(CaseLabels);
+ }
+
+ ~SwitchScope() {
+ this->Ctx->BreakLabel = OldBreakLabel;
+ this->Ctx->DefaultLabel = OldDefaultLabel;
+ this->Ctx->CaseLabels = std::move(OldCaseLabels);
+ }
+
+private:
+ OptLabelTy OldBreakLabel;
+ OptLabelTy OldDefaultLabel;
+ CaseMap OldCaseLabels;
+};
+
} // namespace interp
} // namespace clang
@@ -3603,6 +3666,642 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
return this->emitThis(E);
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitStmt(const Stmt *S) {
+ switch (S->getStmtClass()) {
+ case Stmt::CompoundStmtClass:
+ return visitCompoundStmt(cast<CompoundStmt>(S));
+ case Stmt::DeclStmtClass:
+ return visitDeclStmt(cast<DeclStmt>(S));
+ case Stmt::ReturnStmtClass:
+ return visitReturnStmt(cast<ReturnStmt>(S));
+ case Stmt::IfStmtClass:
+ return visitIfStmt(cast<IfStmt>(S));
+ case Stmt::WhileStmtClass:
+ return visitWhileStmt(cast<WhileStmt>(S));
+ case Stmt::DoStmtClass:
+ return visitDoStmt(cast<DoStmt>(S));
+ case Stmt::ForStmtClass:
+ return visitForStmt(cast<ForStmt>(S));
+ case Stmt::CXXForRangeStmtClass:
+ return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
+ case Stmt::BreakStmtClass:
+ return visitBreakStmt(cast<BreakStmt>(S));
+ case Stmt::ContinueStmtClass:
+ return visitContinueStmt(cast<ContinueStmt>(S));
+ case Stmt::SwitchStmtClass:
+ return visitSwitchStmt(cast<SwitchStmt>(S));
+ case Stmt::CaseStmtClass:
+ return visitCaseStmt(cast<CaseStmt>(S));
+ case Stmt::DefaultStmtClass:
+ return visitDefaultStmt(cast<DefaultStmt>(S));
+ case Stmt::AttributedStmtClass:
+ return visitAttributedStmt(cast<AttributedStmt>(S));
+ case Stmt::CXXTryStmtClass:
+ return visitCXXTryStmt(cast<CXXTryStmt>(S));
+ case Stmt::NullStmtClass:
+ return true;
+ // Always invalid statements.
+ case Stmt::GCCAsmStmtClass:
+ case Stmt::MSAsmStmtClass:
+ case Stmt::GotoStmtClass:
+ return this->emitInvalid(S);
+ case Stmt::LabelStmtClass:
+ return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
+ default: {
+ if (const auto *E = dyn_cast<Expr>(S))
+ return this->discard(E);
+ return false;
+ }
+ }
+}
+
+/// Visits the given statment without creating a variable
+/// scope for it in case it is a compound statement.
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitLoopBody(const Stmt *S) {
+ if (isa<NullStmt>(S))
+ return true;
+
+ if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
+ for (auto *InnerStmt : CS->body())
+ if (!visitStmt(InnerStmt))
+ return false;
+ return true;
+ }
+
+ return this->visitStmt(S);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
+ BlockScope<Emitter> Scope(this);
+ for (auto *InnerStmt : S->body())
+ if (!visitStmt(InnerStmt))
+ return false;
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
+ for (auto *D : DS->decls()) {
+ if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl,
+ FunctionDecl>(D))
+ continue;
+
+ const auto *VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return false;
+ if (!this->visitVarDecl(VD))
+ return false;
+ }
+
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
+ if (const Expr *RE = RS->getRetValue()) {
+ ExprScope<Emitter> RetScope(this);
+ if (ReturnType) {
+ // Primitive types are simply returned.
+ if (!this->visit(RE))
+ return false;
+ this->emitCleanup();
+ return this->emitRet(*ReturnType, RS);
+ } else if (RE->getType()->isVoidType()) {
+ if (!this->visit(RE))
+ return false;
+ } else {
+ // RVO - construct the value in the return location.
+ if (!this->emitRVOPtr(RE))
+ return false;
+ if (!this->visitInitializer(RE))
+ return false;
+ if (!this->emitPopPtr(RE))
+ return false;
+
+ this->emitCleanup();
+ return this->emitRetVoid(RS);
+ }
+ }
+
+ // Void return.
+ this->emitCleanup();
+ return this->emitRetVoid(RS);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitIfStmt(const IfStmt *IS) {
+ BlockScope<Emitter> IfScope(this);
+
+ if (IS->isNonNegatedConsteval())
+ return visitStmt(IS->getThen());
+ if (IS->isNegatedConsteval())
+ return IS->getElse() ? visitStmt(IS->getElse()) : true;
+
+ if (auto *CondInit = IS->getInit())
+ if (!visitStmt(CondInit))
+ return false;
+
+ if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
+ if (!visitDeclStmt(CondDecl))
+ return false;
+
+ if (!this->visitBool(IS->getCond()))
+ return false;
+
+ if (const Stmt *Else = IS->getElse()) {
+ LabelTy LabelElse = this->getLabel();
+ LabelTy LabelEnd = this->getLabel();
+ if (!this->jumpFalse(LabelElse))
+ return false;
+ if (!visitStmt(IS->getThen()))
+ return false;
+ if (!this->jump(LabelEnd))
+ return false;
+ this->emitLabel(LabelElse);
+ if (!visitStmt(Else))
+ return false;
+ this->emitLabel(LabelEnd);
+ } else {
+ LabelTy LabelEnd = this->getLabel();
+ if (!this->jumpFalse(LabelEnd))
+ return false;
+ if (!visitStmt(IS->getThen()))
+ return false;
+ this->emitLabel(LabelEnd);
+ }
+
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
+ const Expr *Cond = S->getCond();
+ const Stmt *Body = S->getBody();
+
+ LabelTy CondLabel = this->getLabel(); // Label before the condition.
+ LabelTy EndLabel = this->getLabel(); // Label after the loop.
+ LoopScope<Emitter> LS(this, EndLabel, CondLabel);
+
+ this->emitLabel(CondLabel);
+
+ if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
+ if (!visitDeclStmt(CondDecl))
+ return false;
+
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+
+ LocalScope<Emitter> Scope(this);
+ {
+ DestructorScope<Emitter> DS(Scope);
+ if (!this->visitLoopBody(Body))
+ return false;
+ }
+
+ if (!this->jump(CondLabel))
+ return false;
+ this->emitLabel(EndLabel);
+
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitDoStmt(const DoStmt *S) {
+ const Expr *Cond = S->getCond();
+ const Stmt *Body = S->getBody();
+
+ LabelTy StartLabel = this->getLabel();
+ LabelTy EndLabel = this->getLabel();
+ LabelTy CondLabel = this->getLabel();
+ LoopScope<Emitter> LS(this, EndLabel, CondLabel);
+ LocalScope<Emitter> Scope(this);
+
+ this->emitLabel(StartLabel);
+ {
+ DestructorScope<Emitter> DS(Scope);
+
+ if (!this->visitLoopBody(Body))
+ return false;
+ this->emitLabel(CondLabel);
+ if (!this->visitBool(Cond))
+ return false;
+ }
+ if (!this->jumpTrue(StartLabel))
+ return false;
+
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitForStmt(const ForStmt *S) {
+ // for (Init; Cond; Inc) { Body }
+ const Stmt *Init = S->getInit();
+ const Expr *Cond = S->getCond();
+ const Expr *Inc = S->getInc();
+ const Stmt *Body = S->getBody();
+
+ LabelTy EndLabel = this->getLabel();
+ LabelTy CondLabel = this->getLabel();
+ LabelTy IncLabel = this->getLabel();
+ LoopScope<Emitter> LS(this, EndLabel, IncLabel);
+ LocalScope<Emitter> Scope(this);
+
+ if (Init && !this->visitStmt(Init))
+ return false;
+ this->emitLabel(CondLabel);
+
+ if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
+ if (!visitDeclStmt(CondDecl))
+ return false;
+
+ if (Cond) {
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+ }
+
+ {
+ DestructorScope<Emitter> DS(Scope);
+
+ if (Body && !this->visitLoopBody(Body))
+ return false;
+ this->emitLabel(IncLabel);
+ if (Inc && !this->discard(Inc))
+ return false;
+ }
+
+ if (!this->jump(CondLabel))
+ return false;
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
+ const Stmt *Init = S->getInit();
+ const Expr *Cond = S->getCond();
+ const Expr *Inc = S->getInc();
+ const Stmt *Body = S->getBody();
+ const Stmt *BeginStmt = S->getBeginStmt();
+ const Stmt *RangeStmt = S->getRangeStmt();
+ const Stmt *EndStmt = S->getEndStmt();
+ const VarDecl *LoopVar = S->getLoopVariable();
+
+ LabelTy EndLabel = this->getLabel();
+ LabelTy CondLabel = this->getLabel();
+ LabelTy IncLabel = this->getLabel();
+ LoopScope<Emitter> LS(this, EndLabel, IncLabel);
+
+ // Emit declarations needed in the loop.
+ if (Init && !this->visitStmt(Init))
+ return false;
+ if (!this->visitStmt(RangeStmt))
+ return false;
+ if (!this->visitStmt(BeginStmt))
+ return false;
+ if (!this->visitStmt(EndStmt))
+ return false;
+
+ // Now the condition as well as the loop variable assignment.
+ this->emitLabel(CondLabel);
+ if (!this->visitBool(Cond))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+
+ if (!this->visitVarDecl(LoopVar))
+ return false;
+
+ // Body.
+ LocalScope<Emitter> Scope(this);
+ {
+ DestructorScope<Emitter> DS(Scope);
+
+ if (!this->visitLoopBody(Body))
+ return false;
+ this->emitLabel(IncLabel);
+ if (!this->discard(Inc))
+ return false;
+ }
+ if (!this->jump(CondLabel))
+ return false;
+
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
+ if (!BreakLabel)
+ return false;
+
+ this->VarScope->emitDestructors();
+ return this->jump(*BreakLabel);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
+ if (!ContinueLabel)
+ return false;
+
+ this->VarScope->emitDestructors();
+ return this->jump(*ContinueLabel);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
+ const Expr *Cond = S->getCond();
+ PrimType CondT = this->classifyPrim(Cond->getType());
+
+ LabelTy EndLabel = this->getLabel();
+ OptLabelTy DefaultLabel = std::nullopt;
+ unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
+
+ if (const auto *CondInit = S->getInit())
+ if (!visitStmt(CondInit))
+ return false;
+
+ if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
+ if (!visitDeclStmt(CondDecl))
+ return false;
+
+ // Initialize condition variable.
+ if (!this->visit(Cond))
+ return false;
+ if (!this->emitSetLocal(CondT, CondVar, S))
+ return false;
+
+ CaseMap CaseLabels;
+ // Create labels and comparison ops for all case statements.
+ for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
+ // FIXME: Implement ranges.
+ if (CS->caseStmtIsGNURange())
+ return false;
+ CaseLabels[SC] = this->getLabel();
+
+ const Expr *Value = CS->getLHS();
+ PrimType ValueT = this->classifyPrim(Value->getType());
+
+ // Compare the case statement's value to the switch condition.
+ if (!this->emitGetLocal(CondT, CondVar, CS))
+ return false;
+ if (!this->visit(Value))
+ return false;
+
+ // Compare and jump to the case label.
+ if (!this->emitEQ(ValueT, S))
+ return false;
+ if (!this->jumpTrue(CaseLabels[CS]))
+ return false;
+ } else {
+ assert(!DefaultLabel);
+ DefaultLabel = this->getLabel();
+ }
+ }
+
+ // If none of the conditions above were true, fall through to the default
+ // statement or jump after the switch statement.
+ if (DefaultLabel) {
+ if (!this->jump(*DefaultLabel))
+ return false;
+ } else {
+ if (!this->jump(EndLabel))
+ return false;
+ }
+
+ SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
+ if (!this->visitStmt(S->getBody()))
+ return false;
+ this->emitLabel(EndLabel);
+ return true;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitCaseStmt(const CaseStmt *S) {
+ this->emitLabel(CaseLabels[S]);
+ return this->visitStmt(S->getSubStmt());
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
+ this->emitLabel(*DefaultLabel);
+ return this->visitStmt(S->getSubStmt());
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
+ if (this->Ctx.getLangOpts().CXXAssumptions &&
+ !this->Ctx.getLangOpts().MSVCCompat) {
+ for (const Attr *A : S->getAttrs()) {
+ auto *AA = dyn_cast<CXXAssumeAttr>(A);
+ if (!AA)
+ continue;
+
+ assert(isa<NullStmt>(S->getSubStmt()));
+
+ const Expr *Assumption = AA->getAssumption();
+ if (Assumption->isValueDependent())
+ return false;
+
+ if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
+ continue;
+
+ // Evaluate assumption.
+ if (!this->visitBool(Assumption))
+ return false;
+
+ if (!this->emitAssume(Assumption))
+ return false;
+ }
+ }
+
+ // Ignore other attributes.
+ return this->visitStmt(S->getSubStmt());
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
+ // Ignore all handlers.
+ return this->visitStmt(S->getTryBlock());
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::emitLambdaStaticInvokerBody(
+ const CXXMethodDecl *MD) {
+ assert(MD->isLambdaStaticInvoker());
+ assert(MD->hasBody());
+ assert(cast<CompoundStmt>(MD->getBody())->body_empty());
+
+ const CXXRecordDecl *ClosureClass = MD->getParent();
+ const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
+ assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
+ const Function *Func = this->getFunction(LambdaCallOp);
+ if (!Func)
+ return false;
+ assert(Func->hasThisPointer());
+ assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));
+
+ if (Func->hasRVO()) {
+ if (!this->emitRVOPtr(MD))
+ return false;
+ }
+
+ // The lambda call operator needs an instance pointer, but we don't have
+ // one here, and we don't need one either because the lambda cannot have
+ // any captures, as verified above. Emit a null pointer. This is then
+ // special-cased when interpreting to not emit any misleading diagnostics.
+ if (!this->emitNullPtr(nullptr, MD))
+ return false;
+
+ // Forward all arguments from the static invoker to the lambda call operator.
+ for (const ParmVarDecl *PVD : MD->parameters()) {
+ auto It = this->Params.find(PVD);
+ assert(It != this->Params.end());
+
+ // We do the lvalue-to-rvalue conversion manually here, so no need
+ // to care about references.
+ PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
+ if (!this->emitGetParam(ParamType, It->second.Offset, MD))
+ return false;
+ }
+
+ if (!this->emitCall(Func, 0, LambdaCallOp))
+ return false;
+
+ this->emitCleanup();
+ if (ReturnType)
+ return this->emitRet(*ReturnType, MD);
+
+ // Nothing to do, since we emitted the RVO pointer above.
+ return this->emitRetVoid(MD);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitFunc(const FunctionDecl *F) {
+
+ // Classify the return type.
+ ReturnType = this->classify(F->getReturnType());
+
+ auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
+ const Expr *InitExpr) -> bool {
+ // We don't know what to do with these, so just return false.
+ if (InitExpr->getType().isNull())
+ return false;
+
+ if (std::optional<PrimType> T = this->classify(InitExpr)) {
+ if (!this->visit(InitExpr))
+ return false;
+
+ if (F->isBitField())
+ return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
+ return this->emitInitThisField(*T, FieldOffset, InitExpr);
+ }
+ // Non-primitive case. Get a pointer to the field-to-initialize
+ // on the stack and call visitInitialzer() for it.
+ if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
+ return false;
+
+ if (!this->visitInitializer(InitExpr))
+ return false;
+
+ return this->emitPopPtr(InitExpr);
+ };
+
+ // Emit custom code if this is a lambda static invoker.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
+ MD && MD->isLambdaStaticInvoker())
+ return this->emitLambdaStaticInvokerBody(MD);
+
+ // Constructor. Set up field initializers.
+ if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
+ const RecordDecl *RD = Ctor->getParent();
+ const Record *R = this->getRecord(RD);
+ if (!R)
+ return false;
+
+ for (const auto *Init : Ctor->inits()) {
+ // Scope needed for the initializers.
+ BlockScope<Emitter> Scope(this);
+
+ const Expr *InitExpr = Init->getInit();
+ if (const FieldDecl *Member = Init->getMember()) {
+ const Record::Field *F = R->getField(Member);
+
+ if (!emitFieldInitializer(F, F->Offset, InitExpr))
+ return false;
+ } else if (const Type *Base = Init->getBaseClass()) {
+ const auto *BaseDecl = Base->getAsCXXRecordDecl();
+ assert(BaseDecl);
+
+ if (Init->isBaseVirtual()) {
+ assert(R->getVirtualBase(BaseDecl));
+ if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
+ return false;
+
+ } else {
+ // Base class initializer.
+ // Get This Base and call initializer on it.
+ const Record::Base *B = R->getBase(BaseDecl);
+ assert(B);
+ if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
+ return false;
+ }
+
+ if (!this->visitInitializer(InitExpr))
+ return false;
+ if (!this->emitFinishInitPop(InitExpr))
+ return false;
+ } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
+ assert(IFD->getChainingSize() >= 2);
+
+ unsigned NestedFieldOffset = 0;
+ const Record::Field *NestedField = nullptr;
+ for (const NamedDecl *ND : IFD->chain()) {
+ const auto *FD = cast<FieldDecl>(ND);
+ const Record *FieldRecord =
+ this->P.getOrCreateRecord(FD->getParent());
+ assert(FieldRecord);
+
+ NestedField = FieldRecord->getField(FD);
+ assert(NestedField);
+
+ NestedFieldOffset += NestedField->Offset;
+ }
+ assert(NestedField);
+
+ if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
+ return false;
+ } else {
+ assert(Init->isDelegatingInitializer());
+ if (!this->emitThis(InitExpr))
+ return false;
+ if (!this->visitInitializer(Init->getInit()))
+ return false;
+ if (!this->emitPopPtr(InitExpr))
+ return false;
+ }
+ }
+ }
+
+ if (const auto *Body = F->getBody())
+ if (!visitStmt(Body))
+ return false;
+
+ // Emit a guard return to protect against a code path missing one.
+ if (F->getReturnType()->isVoidType())
+ return this->emitRetVoid(SourceInfo{});
+ return this->emitNoRet(SourceInfo{});
+}
+
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 7bb5304cac71e..40955dd43a907 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -35,6 +35,9 @@ template <class Emitter> class DeclScope;
template <class Emitter> class OptionScope;
template <class Emitter> class ArrayIndexScope;
template <class Emitter> class SourceLocScope;
+template <class Emitter> class LoopScope;
+template <class Emitter> class LabelScope;
+template <class Emitter> class SwitchScope;
/// Compilation context for expressions.
template <class Emitter>
@@ -44,6 +47,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
// Aliases for types defined in the emitter.
using LabelTy = typename Emitter::LabelTy;
using AddrTy = typename Emitter::AddrTy;
+ using OptLabelTy = std::optional<LabelTy>;
+ using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
/// Current compilation context.
Context &Ctx;
@@ -56,7 +61,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
: Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
- // Expression visitors - result returned on interp stack.
+ // Expressions.
bool VisitCastExpr(const CastExpr *E);
bool VisitIntegerLiteral(const IntegerLiteral *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
@@ -130,9 +135,29 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
+ // Statements.
+ bool visitCompoundStmt(const CompoundStmt *S);
+ bool visitLoopBody(const Stmt *S);
+ bool visitDeclStmt(const DeclStmt *DS);
+ bool visitReturnStmt(const ReturnStmt *RS);
+ bool visitIfStmt(const IfStmt *IS);
+ bool visitWhileStmt(const WhileStmt *S);
+ bool visitDoStmt(const DoStmt *S);
+ bool visitForStmt(const ForStmt *S);
+ bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
+ bool visitBreakStmt(const BreakStmt *S);
+ bool visitContinueStmt(const ContinueStmt *S);
+ bool visitSwitchStmt(const SwitchStmt *S);
+ bool visitCaseStmt(const CaseStmt *S);
+ bool visitDefaultStmt(const DefaultStmt *S);
+ bool visitAttributedStmt(const AttributedStmt *S);
+ bool visitCXXTryStmt(const CXXTryStmt *S);
+
protected:
+ bool visitStmt(const Stmt *S);
bool visitExpr(const Expr *E) override;
bool visitDecl(const VarDecl *VD) override;
+ bool visitFunc(const FunctionDecl *F) override;
protected:
/// Emits scope cleanup instructions.
@@ -145,8 +170,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
Record *getRecord(QualType Ty);
Record *getRecord(const RecordDecl *RD);
- // Returns a function for the given FunctionDecl.
- // If the function does not exist yet, it is compiled.
+ /// Returns a function for the given FunctionDecl.
+ /// If the function does not exist yet, it is compiled.
const Function *getFunction(const FunctionDecl *FD);
std::optional<PrimType> classify(const Expr *E) const {
@@ -255,6 +280,9 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
friend class OptionScope<Emitter>;
friend class ArrayIndexScope<Emitter>;
friend class SourceLocScope<Emitter>;
+ friend class LoopScope<Emitter>;
+ friend class LabelScope<Emitter>;
+ friend class SwitchScope<Emitter>;
/// Emits a zero initializer.
bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
@@ -298,6 +326,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool emitDestruction(const Descriptor *Desc);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
+ bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
protected:
/// Variable to storage mapping.
@@ -325,6 +354,19 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
/// Flag indicating if we're initializing a global variable.
bool GlobalDecl = false;
+
+ /// Type of the expression returned by the function.
+ std::optional<PrimType> ReturnType;
+
+ /// Switch case mapping.
+ CaseMap CaseLabels;
+
+ /// Point to break to.
+ OptLabelTy BreakLabel;
+ /// Point to continue to.
+ OptLabelTy ContinueLabel;
+ /// Default case label.
+ OptLabelTy DefaultLabel;
};
extern template class ByteCodeExprGen<ByteCodeEmitter>;
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
deleted file mode 100644
index 6ee7898f228de..0000000000000
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ /dev/null
@@ -1,731 +0,0 @@
-//===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ByteCodeStmtGen.h"
-#include "ByteCodeEmitter.h"
-#include "Context.h"
-#include "Function.h"
-#include "PrimType.h"
-
-using namespace clang;
-using namespace clang::interp;
-
-namespace clang {
-namespace interp {
-
-/// Scope managing label targets.
-template <class Emitter> class LabelScope {
-public:
- virtual ~LabelScope() { }
-
-protected:
- LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {}
- /// ByteCodeStmtGen instance.
- ByteCodeStmtGen<Emitter> *Ctx;
-};
-
-/// Sets the context for break/continue statements.
-template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
-public:
- using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
- using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
-
- LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel,
- LabelTy ContinueLabel)
- : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
- OldContinueLabel(Ctx->ContinueLabel) {
- this->Ctx->BreakLabel = BreakLabel;
- this->Ctx->ContinueLabel = ContinueLabel;
- }
-
- ~LoopScope() {
- this->Ctx->BreakLabel = OldBreakLabel;
- this->Ctx->ContinueLabel = OldContinueLabel;
- }
-
-private:
- OptLabelTy OldBreakLabel;
- OptLabelTy OldContinueLabel;
-};
-
-// Sets the context for a switch scope, mapping labels.
-template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
-public:
- using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
- using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
- using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
-
- SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels,
- LabelTy BreakLabel, OptLabelTy DefaultLabel)
- : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
- OldDefaultLabel(this->Ctx->DefaultLabel),
- OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
- this->Ctx->BreakLabel = BreakLabel;
- this->Ctx->DefaultLabel = DefaultLabel;
- this->Ctx->CaseLabels = std::move(CaseLabels);
- }
-
- ~SwitchScope() {
- this->Ctx->BreakLabel = OldBreakLabel;
- this->Ctx->DefaultLabel = OldDefaultLabel;
- this->Ctx->CaseLabels = std::move(OldCaseLabels);
- }
-
-private:
- OptLabelTy OldBreakLabel;
- OptLabelTy OldDefaultLabel;
- CaseMap OldCaseLabels;
-};
-
-} // namespace interp
-} // namespace clang
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::emitLambdaStaticInvokerBody(
- const CXXMethodDecl *MD) {
- assert(MD->isLambdaStaticInvoker());
- assert(MD->hasBody());
- assert(cast<CompoundStmt>(MD->getBody())->body_empty());
-
- const CXXRecordDecl *ClosureClass = MD->getParent();
- const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
- assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
- const Function *Func = this->getFunction(LambdaCallOp);
- if (!Func)
- return false;
- assert(Func->hasThisPointer());
- assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));
-
- if (Func->hasRVO()) {
- if (!this->emitRVOPtr(MD))
- return false;
- }
-
- // The lambda call operator needs an instance pointer, but we don't have
- // one here, and we don't need one either because the lambda cannot have
- // any captures, as verified above. Emit a null pointer. This is then
- // special-cased when interpreting to not emit any misleading diagnostics.
- if (!this->emitNullPtr(nullptr, MD))
- return false;
-
- // Forward all arguments from the static invoker to the lambda call operator.
- for (const ParmVarDecl *PVD : MD->parameters()) {
- auto It = this->Params.find(PVD);
- assert(It != this->Params.end());
-
- // We do the lvalue-to-rvalue conversion manually here, so no need
- // to care about references.
- PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
- if (!this->emitGetParam(ParamType, It->second.Offset, MD))
- return false;
- }
-
- if (!this->emitCall(Func, 0, LambdaCallOp))
- return false;
-
- this->emitCleanup();
- if (ReturnType)
- return this->emitRet(*ReturnType, MD);
-
- // Nothing to do, since we emitted the RVO pointer above.
- return this->emitRetVoid(MD);
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
- // Classify the return type.
- ReturnType = this->classify(F->getReturnType());
-
- auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
- const Expr *InitExpr) -> bool {
- // We don't know what to do with these, so just return false.
- if (InitExpr->getType().isNull())
- return false;
-
- if (std::optional<PrimType> T = this->classify(InitExpr)) {
- if (!this->visit(InitExpr))
- return false;
-
- if (F->isBitField())
- return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
- return this->emitInitThisField(*T, FieldOffset, InitExpr);
- }
- // Non-primitive case. Get a pointer to the field-to-initialize
- // on the stack and call visitInitialzer() for it.
- if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
- return false;
-
- if (!this->visitInitializer(InitExpr))
- return false;
-
- return this->emitPopPtr(InitExpr);
- };
-
- // Emit custom code if this is a lambda static invoker.
- if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
- MD && MD->isLambdaStaticInvoker())
- return this->emitLambdaStaticInvokerBody(MD);
-
- // Constructor. Set up field initializers.
- if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
- const RecordDecl *RD = Ctor->getParent();
- const Record *R = this->getRecord(RD);
- if (!R)
- return false;
-
- for (const auto *Init : Ctor->inits()) {
- // Scope needed for the initializers.
- BlockScope<Emitter> Scope(this);
-
- const Expr *InitExpr = Init->getInit();
- if (const FieldDecl *Member = Init->getMember()) {
- const Record::Field *F = R->getField(Member);
-
- if (!emitFieldInitializer(F, F->Offset, InitExpr))
- return false;
- } else if (const Type *Base = Init->getBaseClass()) {
- const auto *BaseDecl = Base->getAsCXXRecordDecl();
- assert(BaseDecl);
-
- if (Init->isBaseVirtual()) {
- assert(R->getVirtualBase(BaseDecl));
- if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
- return false;
-
- } else {
- // Base class initializer.
- // Get This Base and call initializer on it.
- const Record::Base *B = R->getBase(BaseDecl);
- assert(B);
- if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
- return false;
- }
-
- if (!this->visitInitializer(InitExpr))
- return false;
- if (!this->emitFinishInitPop(InitExpr))
- return false;
- } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
- assert(IFD->getChainingSize() >= 2);
-
- unsigned NestedFieldOffset = 0;
- const Record::Field *NestedField = nullptr;
- for (const NamedDecl *ND : IFD->chain()) {
- const auto *FD = cast<FieldDecl>(ND);
- const Record *FieldRecord =
- this->P.getOrCreateRecord(FD->getParent());
- assert(FieldRecord);
-
- NestedField = FieldRecord->getField(FD);
- assert(NestedField);
-
- NestedFieldOffset += NestedField->Offset;
- }
- assert(NestedField);
-
- if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
- return false;
- } else {
- assert(Init->isDelegatingInitializer());
- if (!this->emitThis(InitExpr))
- return false;
- if (!this->visitInitializer(Init->getInit()))
- return false;
- if (!this->emitPopPtr(InitExpr))
- return false;
- }
- }
- }
-
- if (const auto *Body = F->getBody())
- if (!visitStmt(Body))
- return false;
-
- // Emit a guard return to protect against a code path missing one.
- if (F->getReturnType()->isVoidType())
- return this->emitRetVoid(SourceInfo{});
- else
- return this->emitNoRet(SourceInfo{});
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
- switch (S->getStmtClass()) {
- case Stmt::CompoundStmtClass:
- return visitCompoundStmt(cast<CompoundStmt>(S));
- case Stmt::DeclStmtClass:
- return visitDeclStmt(cast<DeclStmt>(S));
- case Stmt::ReturnStmtClass:
- return visitReturnStmt(cast<ReturnStmt>(S));
- case Stmt::IfStmtClass:
- return visitIfStmt(cast<IfStmt>(S));
- case Stmt::WhileStmtClass:
- return visitWhileStmt(cast<WhileStmt>(S));
- case Stmt::DoStmtClass:
- return visitDoStmt(cast<DoStmt>(S));
- case Stmt::ForStmtClass:
- return visitForStmt(cast<ForStmt>(S));
- case Stmt::CXXForRangeStmtClass:
- return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
- case Stmt::BreakStmtClass:
- return visitBreakStmt(cast<BreakStmt>(S));
- case Stmt::ContinueStmtClass:
- return visitContinueStmt(cast<ContinueStmt>(S));
- case Stmt::SwitchStmtClass:
- return visitSwitchStmt(cast<SwitchStmt>(S));
- case Stmt::CaseStmtClass:
- return visitCaseStmt(cast<CaseStmt>(S));
- case Stmt::DefaultStmtClass:
- return visitDefaultStmt(cast<DefaultStmt>(S));
- case Stmt::AttributedStmtClass:
- return visitAttributedStmt(cast<AttributedStmt>(S));
- case Stmt::CXXTryStmtClass:
- return visitCXXTryStmt(cast<CXXTryStmt>(S));
- case Stmt::NullStmtClass:
- return true;
- // Always invalid statements.
- case Stmt::GCCAsmStmtClass:
- case Stmt::MSAsmStmtClass:
- case Stmt::GotoStmtClass:
- return this->emitInvalid(S);
- case Stmt::LabelStmtClass:
- return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
- default: {
- if (auto *Exp = dyn_cast<Expr>(S))
- return this->discard(Exp);
- return false;
- }
- }
-}
-
-/// Visits the given statment without creating a variable
-/// scope for it in case it is a compound statement.
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitLoopBody(const Stmt *S) {
- if (isa<NullStmt>(S))
- return true;
-
- if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
- for (auto *InnerStmt : CS->body())
- if (!visitStmt(InnerStmt))
- return false;
- return true;
- }
-
- return this->visitStmt(S);
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
- const CompoundStmt *CompoundStmt) {
- BlockScope<Emitter> Scope(this);
- for (auto *InnerStmt : CompoundStmt->body())
- if (!visitStmt(InnerStmt))
- return false;
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
- for (auto *D : DS->decls()) {
- if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl,
- FunctionDecl>(D))
- continue;
-
- const auto *VD = dyn_cast<VarDecl>(D);
- if (!VD)
- return false;
- if (!this->visitVarDecl(VD))
- return false;
- }
-
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
- if (const Expr *RE = RS->getRetValue()) {
- ExprScope<Emitter> RetScope(this);
- if (ReturnType) {
- // Primitive types are simply returned.
- if (!this->visit(RE))
- return false;
- this->emitCleanup();
- return this->emitRet(*ReturnType, RS);
- } else if (RE->getType()->isVoidType()) {
- if (!this->visit(RE))
- return false;
- } else {
- // RVO - construct the value in the return location.
- if (!this->emitRVOPtr(RE))
- return false;
- if (!this->visitInitializer(RE))
- return false;
- if (!this->emitPopPtr(RE))
- return false;
-
- this->emitCleanup();
- return this->emitRetVoid(RS);
- }
- }
-
- // Void return.
- this->emitCleanup();
- return this->emitRetVoid(RS);
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
- BlockScope<Emitter> IfScope(this);
-
- if (IS->isNonNegatedConsteval())
- return visitStmt(IS->getThen());
- if (IS->isNegatedConsteval())
- return IS->getElse() ? visitStmt(IS->getElse()) : true;
-
- if (auto *CondInit = IS->getInit())
- if (!visitStmt(CondInit))
- return false;
-
- if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
- if (!visitDeclStmt(CondDecl))
- return false;
-
- if (!this->visitBool(IS->getCond()))
- return false;
-
- if (const Stmt *Else = IS->getElse()) {
- LabelTy LabelElse = this->getLabel();
- LabelTy LabelEnd = this->getLabel();
- if (!this->jumpFalse(LabelElse))
- return false;
- if (!visitStmt(IS->getThen()))
- return false;
- if (!this->jump(LabelEnd))
- return false;
- this->emitLabel(LabelElse);
- if (!visitStmt(Else))
- return false;
- this->emitLabel(LabelEnd);
- } else {
- LabelTy LabelEnd = this->getLabel();
- if (!this->jumpFalse(LabelEnd))
- return false;
- if (!visitStmt(IS->getThen()))
- return false;
- this->emitLabel(LabelEnd);
- }
-
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
- const Expr *Cond = S->getCond();
- const Stmt *Body = S->getBody();
-
- LabelTy CondLabel = this->getLabel(); // Label before the condition.
- LabelTy EndLabel = this->getLabel(); // Label after the loop.
- LoopScope<Emitter> LS(this, EndLabel, CondLabel);
-
- this->emitLabel(CondLabel);
-
- if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
- if (!visitDeclStmt(CondDecl))
- return false;
-
- if (!this->visitBool(Cond))
- return false;
- if (!this->jumpFalse(EndLabel))
- return false;
-
- LocalScope<Emitter> Scope(this);
- {
- DestructorScope<Emitter> DS(Scope);
- if (!this->visitLoopBody(Body))
- return false;
- }
-
- if (!this->jump(CondLabel))
- return false;
- this->emitLabel(EndLabel);
-
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitDoStmt(const DoStmt *S) {
- const Expr *Cond = S->getCond();
- const Stmt *Body = S->getBody();
-
- LabelTy StartLabel = this->getLabel();
- LabelTy EndLabel = this->getLabel();
- LabelTy CondLabel = this->getLabel();
- LoopScope<Emitter> LS(this, EndLabel, CondLabel);
- LocalScope<Emitter> Scope(this);
-
- this->emitLabel(StartLabel);
- {
- DestructorScope<Emitter> DS(Scope);
-
- if (!this->visitLoopBody(Body))
- return false;
- this->emitLabel(CondLabel);
- if (!this->visitBool(Cond))
- return false;
- }
- if (!this->jumpTrue(StartLabel))
- return false;
-
- this->emitLabel(EndLabel);
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitForStmt(const ForStmt *S) {
- // for (Init; Cond; Inc) { Body }
- const Stmt *Init = S->getInit();
- const Expr *Cond = S->getCond();
- const Expr *Inc = S->getInc();
- const Stmt *Body = S->getBody();
-
- LabelTy EndLabel = this->getLabel();
- LabelTy CondLabel = this->getLabel();
- LabelTy IncLabel = this->getLabel();
- LoopScope<Emitter> LS(this, EndLabel, IncLabel);
- LocalScope<Emitter> Scope(this);
-
- if (Init && !this->visitStmt(Init))
- return false;
- this->emitLabel(CondLabel);
-
- if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
- if (!visitDeclStmt(CondDecl))
- return false;
- if (Cond) {
- if (!this->visitBool(Cond))
- return false;
- if (!this->jumpFalse(EndLabel))
- return false;
- }
-
- {
- DestructorScope<Emitter> DS(Scope);
-
- if (Body && !this->visitLoopBody(Body))
- return false;
- this->emitLabel(IncLabel);
- if (Inc && !this->discard(Inc))
- return false;
- }
-
- if (!this->jump(CondLabel))
- return false;
- this->emitLabel(EndLabel);
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
- const Stmt *Init = S->getInit();
- const Expr *Cond = S->getCond();
- const Expr *Inc = S->getInc();
- const Stmt *Body = S->getBody();
- const Stmt *BeginStmt = S->getBeginStmt();
- const Stmt *RangeStmt = S->getRangeStmt();
- const Stmt *EndStmt = S->getEndStmt();
- const VarDecl *LoopVar = S->getLoopVariable();
-
- LabelTy EndLabel = this->getLabel();
- LabelTy CondLabel = this->getLabel();
- LabelTy IncLabel = this->getLabel();
- LoopScope<Emitter> LS(this, EndLabel, IncLabel);
-
- // Emit declarations needed in the loop.
- if (Init && !this->visitStmt(Init))
- return false;
- if (!this->visitStmt(RangeStmt))
- return false;
- if (!this->visitStmt(BeginStmt))
- return false;
- if (!this->visitStmt(EndStmt))
- return false;
-
- // Now the condition as well as the loop variable assignment.
- this->emitLabel(CondLabel);
- if (!this->visitBool(Cond))
- return false;
- if (!this->jumpFalse(EndLabel))
- return false;
-
- if (!this->visitVarDecl(LoopVar))
- return false;
-
- // Body.
- LocalScope<Emitter> Scope(this);
- {
- DestructorScope<Emitter> DS(Scope);
-
- if (!this->visitLoopBody(Body))
- return false;
- this->emitLabel(IncLabel);
- if (!this->discard(Inc))
- return false;
- }
- if (!this->jump(CondLabel))
- return false;
-
- this->emitLabel(EndLabel);
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
- if (!BreakLabel)
- return false;
-
- this->VarScope->emitDestructors();
- return this->jump(*BreakLabel);
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
- if (!ContinueLabel)
- return false;
-
- this->VarScope->emitDestructors();
- return this->jump(*ContinueLabel);
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
- const Expr *Cond = S->getCond();
-
- LabelTy EndLabel = this->getLabel();
- OptLabelTy DefaultLabel = std::nullopt;
-
- if (const auto *CondInit = S->getInit())
- if (!visitStmt(CondInit))
- return false;
-
- if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
- if (!visitDeclStmt(CondDecl))
- return false;
-
- // Initialize condition variable.
- PrimType CondT = this->classifyPrim(Cond->getType());
- unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
- if (!this->visit(Cond))
- return false;
- if (!this->emitSetLocal(CondT, CondVar, S))
- return false;
-
- CaseMap CaseLabels;
- // Create labels and comparison ops for all case statements.
- for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
- SC = SC->getNextSwitchCase()) {
- if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
- // FIXME: Implement ranges.
- if (CS->caseStmtIsGNURange())
- return false;
- CaseLabels[SC] = this->getLabel();
-
- const Expr *Value = CS->getLHS();
- PrimType ValueT = this->classifyPrim(Value->getType());
-
- // Compare the case statement's value to the switch condition.
- if (!this->emitGetLocal(CondT, CondVar, CS))
- return false;
- if (!this->visit(Value))
- return false;
-
- // Compare and jump to the case label.
- if (!this->emitEQ(ValueT, S))
- return false;
- if (!this->jumpTrue(CaseLabels[CS]))
- return false;
- } else {
- assert(!DefaultLabel);
- DefaultLabel = this->getLabel();
- }
- }
-
- // If none of the conditions above were true, fall through to the default
- // statement or jump after the switch statement.
- if (DefaultLabel) {
- if (!this->jump(*DefaultLabel))
- return false;
- } else {
- if (!this->jump(EndLabel))
- return false;
- }
-
- SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
- if (!this->visitStmt(S->getBody()))
- return false;
- this->emitLabel(EndLabel);
- return true;
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitCaseStmt(const CaseStmt *S) {
- this->emitLabel(CaseLabels[S]);
- return this->visitStmt(S->getSubStmt());
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
- this->emitLabel(*DefaultLabel);
- return this->visitStmt(S->getSubStmt());
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
-
- if (this->Ctx.getLangOpts().CXXAssumptions &&
- !this->Ctx.getLangOpts().MSVCCompat) {
- for (const Attr *A : S->getAttrs()) {
- auto *AA = dyn_cast<CXXAssumeAttr>(A);
- if (!AA)
- continue;
-
- assert(isa<NullStmt>(S->getSubStmt()));
-
- const Expr *Assumption = AA->getAssumption();
- if (Assumption->isValueDependent())
- return false;
-
- if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
- continue;
-
- // Evaluate assumption.
- if (!this->visitBool(Assumption))
- return false;
-
- if (!this->emitAssume(Assumption))
- return false;
- }
- }
-
- // Ignore other attributes.
- return this->visitStmt(S->getSubStmt());
-}
-
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
- // Ignore all handlers.
- return this->visitStmt(S->getTryBlock());
-}
-
-namespace clang {
-namespace interp {
-
-template class ByteCodeStmtGen<ByteCodeEmitter>;
-
-} // namespace interp
-} // namespace clang
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.h b/clang/lib/AST/Interp/ByteCodeStmtGen.h
deleted file mode 100644
index d7e6e5042c274..0000000000000
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===--- ByteCodeStmtGen.h - Code generator for expressions -----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines the constexpr bytecode compiler.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_AST_INTERP_BYTECODESTMTGEN_H
-#define LLVM_CLANG_AST_INTERP_BYTECODESTMTGEN_H
-
-#include "ByteCodeEmitter.h"
-#include "ByteCodeExprGen.h"
-#include "EvalEmitter.h"
-#include "PrimType.h"
-#include "clang/AST/StmtVisitor.h"
-
-namespace clang {
-namespace interp {
-
-template <class Emitter> class LoopScope;
-template <class Emitter> class SwitchScope;
-template <class Emitter> class LabelScope;
-
-/// Compilation context for statements.
-template <class Emitter>
-class ByteCodeStmtGen final : public ByteCodeExprGen<Emitter> {
- using LabelTy = typename Emitter::LabelTy;
- using AddrTy = typename Emitter::AddrTy;
- using OptLabelTy = std::optional<LabelTy>;
- using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
-
-public:
- template<typename... Tys>
- ByteCodeStmtGen(Tys&&... Args)
- : ByteCodeExprGen<Emitter>(std::forward<Tys>(Args)...) {}
-
-protected:
- bool visitFunc(const FunctionDecl *F) override;
-
-private:
- friend class LabelScope<Emitter>;
- friend class LoopScope<Emitter>;
- friend class SwitchScope<Emitter>;
-
- // Statement visitors.
- bool visitStmt(const Stmt *S);
- bool visitCompoundStmt(const CompoundStmt *S);
- bool visitLoopBody(const Stmt *S);
- bool visitDeclStmt(const DeclStmt *DS);
- bool visitReturnStmt(const ReturnStmt *RS);
- bool visitIfStmt(const IfStmt *IS);
- bool visitWhileStmt(const WhileStmt *S);
- bool visitDoStmt(const DoStmt *S);
- bool visitForStmt(const ForStmt *S);
- bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
- bool visitBreakStmt(const BreakStmt *S);
- bool visitContinueStmt(const ContinueStmt *S);
- bool visitSwitchStmt(const SwitchStmt *S);
- bool visitCaseStmt(const CaseStmt *S);
- bool visitDefaultStmt(const DefaultStmt *S);
- bool visitAttributedStmt(const AttributedStmt *S);
- bool visitCXXTryStmt(const CXXTryStmt *S);
-
- bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
-
- /// Type of the expression returned by the function.
- std::optional<PrimType> ReturnType;
-
- /// Switch case mapping.
- CaseMap CaseLabels;
-
- /// Point to break to.
- OptLabelTy BreakLabel;
- /// Point to continue to.
- OptLabelTy ContinueLabel;
- /// Default case label.
- OptLabelTy DefaultLabel;
-};
-
-extern template class ByteCodeStmtGen<ByteCodeEmitter>;
-extern template class ByteCodeExprGen<EvalEmitter>;
-
-} // namespace interp
-} // namespace clang
-
-#endif
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 98d1837204ebc..338165e03586a 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -9,7 +9,6 @@
#include "Context.h"
#include "ByteCodeEmitter.h"
#include "ByteCodeExprGen.h"
-#include "ByteCodeStmtGen.h"
#include "EvalEmitter.h"
#include "Interp.h"
#include "InterpFrame.h"
@@ -30,7 +29,7 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
assert(Stk.empty());
Function *Func = P->getFunction(FD);
if (!Func || !Func->hasBody())
- Func = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
+ Func = ByteCodeExprGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
APValue DummyResult;
if (!Run(Parent, Func, DummyResult))
@@ -261,7 +260,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
return Func;
if (!Func || WasNotDefined) {
- if (auto F = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
+ if (auto F = ByteCodeExprGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}
diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h
index 98d6026bbcce4..d9da2dc447759 100644
--- a/clang/lib/AST/Interp/EvalEmitter.h
+++ b/clang/lib/AST/Interp/EvalEmitter.h
@@ -56,6 +56,7 @@ class EvalEmitter : public SourceMapper {
/// Methods implemented by the compiler.
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *VD) = 0;
+ virtual bool visitFunc(const FunctionDecl *F) = 0;
/// Emits jumps.
bool jumpTrue(const LabelTy &Label);
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 7b1f719779e90..caff9d01cdfee 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "Program.h"
-#include "ByteCodeStmtGen.h"
#include "Context.h"
#include "Function.h"
#include "Integral.h"
>From b7f80c752528c291300885fd9f916f82bd2496ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 2 Mar 2024 17:12:54 +0100
Subject: [PATCH 2/3] [clang][Interp] Rename ByteCodeExprGen to Compiler
---
clang/lib/AST/CMakeLists.txt | 2 +-
.../{ByteCodeExprGen.cpp => Compiler.cpp} | 354 ++++++++----------
.../Interp/{ByteCodeExprGen.h => Compiler.h} | 36 +-
clang/lib/AST/Interp/Context.cpp | 12 +-
4 files changed, 189 insertions(+), 215 deletions(-)
rename clang/lib/AST/Interp/{ByteCodeExprGen.cpp => Compiler.cpp} (92%)
rename clang/lib/AST/Interp/{ByteCodeExprGen.h => Compiler.h} (94%)
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index c5196fbf7ef74..9eae6cc499a4a 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -65,7 +65,7 @@ add_clang_library(clangAST
FormatString.cpp
InheritViz.cpp
Interp/ByteCodeEmitter.cpp
- Interp/ByteCodeExprGen.cpp
+ Interp/Compiler.cpp
Interp/Context.cpp
Interp/Descriptor.cpp
Interp/Disasm.cpp
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/Compiler.cpp
similarity index 92%
rename from clang/lib/AST/Interp/ByteCodeExprGen.cpp
rename to clang/lib/AST/Interp/Compiler.cpp
index 3e06e25c02559..4f424b2a60871 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -1,4 +1,4 @@
-//===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===//
+//===--- Compiler.cpp - Code generator for expressions ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ByteCodeExprGen.h"
+#include "Compiler.h"
#include "ByteCodeEmitter.h"
#include "Context.h"
#include "Floating.h"
@@ -27,7 +27,7 @@ namespace interp {
/// Scope used to handle temporaries in toplevel variable declarations.
template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
public:
- DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
+ DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: VariableScope<Emitter>(Ctx, nullptr), Scope(Ctx->P, VD),
OldGlobalDecl(Ctx->GlobalDecl),
OldInitializingDecl(Ctx->InitializingDecl) {
@@ -35,6 +35,10 @@ template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
Ctx->InitializingDecl = VD;
}
+ void addExtended(const Scope::Local &Local) override {
+ return this->addLocal(Local);
+ }
+
~DeclScope() {
this->Ctx->GlobalDecl = OldGlobalDecl;
this->Ctx->InitializingDecl = OldInitializingDecl;
@@ -50,7 +54,7 @@ template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
template <class Emitter> class OptionScope final {
public:
/// Root constructor, compiling or discarding primitives.
- OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult,
+ OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
bool NewInitializing)
: Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
OldInitializing(Ctx->Initializing) {
@@ -65,7 +69,7 @@ template <class Emitter> class OptionScope final {
private:
/// Parent context.
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
/// Old discard flag to restore.
bool OldDiscardResult;
bool OldInitializing;
@@ -77,19 +81,18 @@ template <class Emitter> class LabelScope {
virtual ~LabelScope() {}
protected:
- LabelScope(ByteCodeExprGen<Emitter> *Ctx) : Ctx(Ctx) {}
- /// ByteCodeExprGen instance.
- ByteCodeExprGen<Emitter> *Ctx;
+ LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {}
+ /// Compiler instance.
+ Compiler<Emitter> *Ctx;
};
/// Sets the context for break/continue statements.
template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
public:
- using LabelTy = typename ByteCodeExprGen<Emitter>::LabelTy;
- using OptLabelTy = typename ByteCodeExprGen<Emitter>::OptLabelTy;
+ using LabelTy = typename Compiler<Emitter>::LabelTy;
+ using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
- LoopScope(ByteCodeExprGen<Emitter> *Ctx, LabelTy BreakLabel,
- LabelTy ContinueLabel)
+ LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
: LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
OldContinueLabel(Ctx->ContinueLabel) {
this->Ctx->BreakLabel = BreakLabel;
@@ -109,12 +112,12 @@ template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
// Sets the context for a switch scope, mapping labels.
template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
public:
- using LabelTy = typename ByteCodeExprGen<Emitter>::LabelTy;
- using OptLabelTy = typename ByteCodeExprGen<Emitter>::OptLabelTy;
- using CaseMap = typename ByteCodeExprGen<Emitter>::CaseMap;
+ using LabelTy = typename Compiler<Emitter>::LabelTy;
+ using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
+ using CaseMap = typename Compiler<Emitter>::CaseMap;
- SwitchScope(ByteCodeExprGen<Emitter> *Ctx, CaseMap &&CaseLabels,
- LabelTy BreakLabel, OptLabelTy DefaultLabel)
+ SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,
+ OptLabelTy DefaultLabel)
: LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
OldDefaultLabel(this->Ctx->DefaultLabel),
OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
@@ -139,7 +142,7 @@ template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
} // namespace clang
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
+bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr();
switch (CE->getCastKind()) {
@@ -577,7 +580,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
+bool Compiler<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
if (DiscardResult)
return true;
@@ -585,7 +588,7 @@ bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
+bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
if (DiscardResult)
return true;
@@ -593,8 +596,7 @@ bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitImaginaryLiteral(
- const ImaginaryLiteral *E) {
+bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
assert(E->getType()->isAnyComplexType());
if (DiscardResult)
return true;
@@ -618,12 +620,12 @@ bool ByteCodeExprGen<Emitter>::VisitImaginaryLiteral(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *E) {
+bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
return this->delegate(E->getSubExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
+bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
// Need short-circuiting for these.
if (BO->isLogicalOp())
return this->VisitLogicalBinOp(BO);
@@ -795,7 +797,7 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
/// Perform addition/subtraction of a pointer and an integer or
/// subtraction of two pointers.
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
+bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
@@ -843,7 +845,7 @@ bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
+bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
assert(E->isLogicalOp());
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
@@ -904,7 +906,7 @@ bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
+bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
// Prepare storage for result.
if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(E);
@@ -1048,7 +1050,8 @@ bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
+bool Compiler<Emitter>::VisitImplicitValueInitExpr(
+ const ImplicitValueInitExpr *E) {
QualType QT = E->getType();
if (std::optional<PrimType> T = classify(QT))
@@ -1131,8 +1134,7 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
- const ArraySubscriptExpr *E) {
+bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
const Expr *Base = E->getBase();
const Expr *Index = E->getIdx();
@@ -1152,9 +1154,9 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
+bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
const Expr *ArrayFiller,
- const Expr *E) {
+ const Expr *E) {
if (E->getType()->isVoidType())
return this->emitInvalid(E);
@@ -1390,8 +1392,8 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
/// Pointer to the array(not the element!) must be on the stack when calling
/// this.
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
- const Expr *Init) {
+bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex,
+ const Expr *Init) {
if (std::optional<PrimType> T = classify(Init->getType())) {
// Visit the primitive element like normal.
if (!this->visit(Init))
@@ -1411,24 +1413,24 @@ bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
+bool Compiler<Emitter>::VisitInitListExpr(const InitListExpr *E) {
return this->visitInitList(E->inits(), E->getArrayFiller(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr(
+bool Compiler<Emitter>::VisitCXXParenListInitExpr(
const CXXParenListInitExpr *E) {
return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
+bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(
const SubstNonTypeTemplateParmExpr *E) {
return this->delegate(E->getReplacement());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
+bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
std::optional<PrimType> T = classify(E->getType());
if (T && E->hasAPValueResult()) {
// Try to emit the APValue directly, without visiting the subexpr.
@@ -1467,7 +1469,7 @@ static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
+bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *E) {
UnaryExprOrTypeTrait Kind = E->getKind();
const ASTContext &ASTCtx = Ctx.getASTContext();
@@ -1559,7 +1561,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
+bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
// 'Base.Member'
const Expr *Base = E->getBase();
const ValueDecl *Member = E->getMemberDecl();
@@ -1611,8 +1613,7 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr(
- const ArrayInitIndexExpr *E) {
+bool Compiler<Emitter>::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
// ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
// stand-alone, e.g. via EvaluateAsInt().
if (!ArrayIndex)
@@ -1621,8 +1622,7 @@ bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr(
- const ArrayInitLoopExpr *E) {
+bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
assert(Initializing);
assert(!DiscardResult);
@@ -1650,7 +1650,7 @@ bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
+bool Compiler<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
const Expr *SourceExpr = E->getSourceExpr();
if (!SourceExpr)
return false;
@@ -1686,7 +1686,7 @@ bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
+bool Compiler<Emitter>::VisitAbstractConditionalOperator(
const AbstractConditionalOperator *E) {
const Expr *Condition = E->getCond();
const Expr *TrueExpr = E->getTrueExpr();
@@ -1718,7 +1718,7 @@ bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
+bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {
if (DiscardResult)
return true;
@@ -1775,13 +1775,13 @@ bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCStringLiteral(
+bool Compiler<Emitter>::VisitObjCStringLiteral(
const ObjCStringLiteral *E) {
return this->delegate(E->getString());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
+bool Compiler<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
auto &A = Ctx.getASTContext();
std::string Str;
A.getObjCEncodingForType(E->getEncodedType(), Str);
@@ -1792,7 +1792,7 @@ bool ByteCodeExprGen<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitSYCLUniqueStableNameExpr(
+bool Compiler<Emitter>::VisitSYCLUniqueStableNameExpr(
const SYCLUniqueStableNameExpr *E) {
if (DiscardResult)
return true;
@@ -1816,7 +1816,7 @@ bool ByteCodeExprGen<Emitter>::VisitSYCLUniqueStableNameExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
+bool Compiler<Emitter>::VisitCharacterLiteral(
const CharacterLiteral *E) {
if (DiscardResult)
return true;
@@ -1824,7 +1824,7 @@ bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
+bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
const CompoundAssignOperator *E) {
const Expr *LHS = E->getLHS();
@@ -1898,7 +1898,7 @@ bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
+bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
const CompoundAssignOperator *E) {
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
@@ -1935,7 +1935,7 @@ bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
+bool Compiler<Emitter>::VisitCompoundAssignOperator(
const CompoundAssignOperator *E) {
const Expr *LHS = E->getLHS();
@@ -2056,8 +2056,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
- const ExprWithCleanups *E) {
+bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {
ExprScope<Emitter> ES(this);
const Expr *SubExpr = E->getSubExpr();
@@ -2067,7 +2066,7 @@ bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
+bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E) {
const Expr *SubExpr = E->getSubExpr();
@@ -2139,14 +2138,13 @@ bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXBindTemporaryExpr(
+bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(
const CXXBindTemporaryExpr *E) {
return this->delegate(E->getSubExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
- const CompoundLiteralExpr *E) {
+bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
const Expr *Init = E->getInitializer();
if (Initializing) {
// We already have a value, just initialize that.
@@ -2211,7 +2209,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
+bool Compiler<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
if (DiscardResult)
return true;
if (E->getType()->isBooleanType())
@@ -2220,15 +2218,14 @@ bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitArrayTypeTraitExpr(
- const ArrayTypeTraitExpr *E) {
+bool Compiler<Emitter>::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
if (DiscardResult)
return true;
return this->emitConst(E->getValue(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
+bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (DiscardResult)
return true;
@@ -2267,7 +2264,7 @@ bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
+bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
if (DiscardResult)
return true;
@@ -2275,7 +2272,7 @@ bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
+bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
if (E->getSubExpr() && !this->discard(E->getSubExpr()))
return false;
@@ -2283,7 +2280,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr(
+bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
const CXXReinterpretCastExpr *E) {
if (!this->discard(E->getSubExpr()))
return false;
@@ -2292,7 +2289,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
+bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
assert(E->getType()->isBooleanType());
if (DiscardResult)
@@ -2301,8 +2298,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
- const CXXConstructExpr *E) {
+bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
QualType T = E->getType();
assert(!classify(T));
@@ -2414,7 +2410,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
+bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
if (DiscardResult)
return true;
@@ -2470,7 +2466,7 @@ bool ByteCodeExprGen<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
+bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
unsigned N = E->getNumComponents();
if (N == 0)
return false;
@@ -2505,7 +2501,7 @@ bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(
+bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *E) {
QualType Ty = E->getType();
@@ -2564,24 +2560,23 @@ bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
+bool Compiler<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
return this->emitConst(E->getPackLength(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitGenericSelectionExpr(
+bool Compiler<Emitter>::VisitGenericSelectionExpr(
const GenericSelectionExpr *E) {
return this->delegate(E->getResultExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitChooseExpr(const ChooseExpr *E) {
+bool Compiler<Emitter>::VisitChooseExpr(const ChooseExpr *E) {
return this->delegate(E->getChosenSubExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCBoolLiteralExpr(
- const ObjCBoolLiteralExpr *E) {
+bool Compiler<Emitter>::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
if (DiscardResult)
return true;
@@ -2589,7 +2584,7 @@ bool ByteCodeExprGen<Emitter>::VisitObjCBoolLiteralExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXInheritedCtorInitExpr(
+bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
const CXXInheritedCtorInitExpr *E) {
const CXXConstructorDecl *Ctor = E->getConstructor();
assert(!Ctor->isTrivial() &&
@@ -2620,14 +2615,13 @@ bool ByteCodeExprGen<Emitter>::VisitCXXInheritedCtorInitExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitExpressionTraitExpr(
- const ExpressionTraitExpr *E) {
+bool Compiler<Emitter>::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
assert(Ctx.getLangOpts().CPlusPlus);
return this->emitConstBool(E->getValue(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
+bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
if (DiscardResult)
return true;
assert(!Initializing);
@@ -2653,7 +2647,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
+bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
assert(classifyPrim(E->getType()) == PT_Bool);
if (DiscardResult)
return true;
@@ -2661,7 +2655,7 @@ bool ByteCodeExprGen<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitConceptSpecializationExpr(
+bool Compiler<Emitter>::VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *E) {
assert(classifyPrim(E->getType()) == PT_Bool);
if (DiscardResult)
@@ -2670,14 +2664,13 @@ bool ByteCodeExprGen<Emitter>::VisitConceptSpecializationExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXRewrittenBinaryOperator(
+bool Compiler<Emitter>::VisitCXXRewrittenBinaryOperator(
const CXXRewrittenBinaryOperator *E) {
return this->delegate(E->getSemanticForm());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitPseudoObjectExpr(
- const PseudoObjectExpr *E) {
+bool Compiler<Emitter>::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
for (const Expr *SemE : E->semantics()) {
if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
@@ -2701,18 +2694,17 @@ bool ByteCodeExprGen<Emitter>::VisitPseudoObjectExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitPackIndexingExpr(
- const PackIndexingExpr *E) {
+bool Compiler<Emitter>::VisitPackIndexingExpr(const PackIndexingExpr *E) {
return this->delegate(E->getSelectedExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
+bool Compiler<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
return this->emitError(E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
+bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
assert(E->getType()->isVoidPointerType());
unsigned Offset = allocateLocalPrimitive(
@@ -2722,7 +2714,7 @@ bool ByteCodeExprGen<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitConvertVectorExpr(
+bool Compiler<Emitter>::VisitConvertVectorExpr(
const ConvertVectorExpr *E) {
assert(Initializing);
const auto *VT = E->getType()->castAs<VectorType>();
@@ -2755,7 +2747,7 @@ bool ByteCodeExprGen<Emitter>::VisitConvertVectorExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitShuffleVectorExpr(
+bool Compiler<Emitter>::VisitShuffleVectorExpr(
const ShuffleVectorExpr *E) {
assert(Initializing);
assert(E->getNumSubExprs() > 2);
@@ -2798,28 +2790,30 @@ bool ByteCodeExprGen<Emitter>::VisitShuffleVectorExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
+bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
if (!E->isExpressibleAsConstantInitializer())
return this->emitInvalid(E);
return this->delegate(E->getSubExpr());
}
-template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
+template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
/*NewInitializing=*/false);
return this->Visit(E);
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) {
+template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
+ if (E->containsErrors())
+ return this->emitError(E);
+
// We're basically doing:
// OptionScope<Emitter> Scope(this, DicardResult, Initializing);
// but that's unnecessary of course.
return this->Visit(E);
}
-template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
+template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
if (E->getType().isNull())
return false;
@@ -2846,7 +2840,7 @@ template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) {
+bool Compiler<Emitter>::visitInitializer(const Expr *E) {
assert(!classify(E->getType()));
if (E->containsErrors())
@@ -2857,8 +2851,7 @@ bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) {
return this->Visit(E);
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
+template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
std::optional<PrimType> T = classify(E->getType());
if (!T) {
// Convert complex values to bool.
@@ -2892,8 +2885,8 @@ bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
- const Expr *E) {
+bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
+ const Expr *E) {
switch (T) {
case PT_Bool:
return this->emitZeroBool(E);
@@ -2931,8 +2924,8 @@ bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
- const Expr *E) {
+bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
+ const Expr *E) {
assert(E);
assert(R);
// Fields
@@ -3000,7 +2993,7 @@ bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
template <class Emitter>
template <typename T>
-bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
+bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
switch (Ty) {
case PT_Sint8:
return this->emitConstSint8(Value, E);
@@ -3034,13 +3027,13 @@ bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
template <class Emitter>
template <typename T>
-bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) {
+bool Compiler<Emitter>::emitConst(T Value, const Expr *E) {
return this->emitConst(Value, classifyPrim(E->getType()), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
- const Expr *E) {
+bool Compiler<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
+ const Expr *E) {
if (Ty == PT_IntAPS)
return this->emitConstIntAPS(Value, E);
if (Ty == PT_IntAP)
@@ -3052,15 +3045,14 @@ bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
+bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
return this->emitConst(Value, classifyPrim(E->getType()), E);
}
template <class Emitter>
-unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
- PrimType Ty,
- bool IsConst,
- bool IsExtended) {
+unsigned Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty,
+ bool IsConst,
+ bool IsExtended) {
// Make sure we don't accidentally register the same decl twice.
if (const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
@@ -3082,11 +3074,10 @@ unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
}
template <class Emitter>
-std::optional<unsigned>
-ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src,
- const ValueDecl *ExtendingDecl) {
+std::optional<unsigned> Compiler<Emitter>::allocateLocal(DeclTy &&Src,
+ const ValueDecl *ExtendingDecl) {
// Make sure we don't accidentally register the same decl twice.
- if ([[maybe_unused]] const auto *VD =
+ if ([[maybe_unused]] const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
assert(!P.getGlobal(VD));
assert(!Locals.contains(VD));
@@ -3125,31 +3116,29 @@ ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src,
}
template <class Emitter>
-const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
+const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
if (const PointerType *PT = dyn_cast<PointerType>(Ty))
return PT->getPointeeType()->getAs<RecordType>();
return Ty->getAs<RecordType>();
}
-template <class Emitter>
-Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
+template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
if (const auto *RecordTy = getRecordTy(Ty))
return getRecord(RecordTy->getDecl());
return nullptr;
}
template <class Emitter>
-Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
+Record *Compiler<Emitter>::getRecord(const RecordDecl *RD) {
return P.getOrCreateRecord(RD);
}
template <class Emitter>
-const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) {
+const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
return Ctx.getOrCreateFunction(FD);
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
+template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
ExprScope<Emitter> RootScope(this);
// Void expressions.
if (E->getType()->isVoidType()) {
@@ -3190,8 +3179,7 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
/// Toplevel visitDecl().
/// We get here from evaluateAsInitializer().
/// We need to evaluate the initializer and return its value.
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
+template <class Emitter> bool Compiler<Emitter>::visitDecl(const VarDecl *VD) {
assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");
// If we've seen the global variable already and the initializer failed,
@@ -3254,7 +3242,7 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
+bool Compiler<Emitter>::visitVarDecl(const VarDecl *VD) {
// We don't know what to do with these, so just return false.
if (VD->getType().isNull())
return false;
@@ -3317,8 +3305,8 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
- PrimType ValType, const Expr *E) {
+bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
+ const Expr *E) {
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
@@ -3344,7 +3332,7 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
+bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
const Expr *E) {
if (Val.isStruct()) {
@@ -3407,7 +3395,7 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
+bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
const Function *Func = getFunction(E->getDirectCallee());
if (!Func)
return false;
@@ -3444,7 +3432,7 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
+bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
if (E->getBuiltinCallee())
return VisitBuiltinCallExpr(E);
@@ -3604,15 +3592,13 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr(
- const CXXDefaultInitExpr *E) {
+bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
SourceLocScope<Emitter> SLS(this, E);
return this->delegate(E->getExpr());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr(
- const CXXDefaultArgExpr *E) {
+bool Compiler<Emitter>::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
SourceLocScope<Emitter> SLS(this, E);
const Expr *SubExpr = E->getExpr();
@@ -3624,8 +3610,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
- const CXXBoolLiteralExpr *E) {
+bool Compiler<Emitter>::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
if (DiscardResult)
return true;
@@ -3633,7 +3618,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
+bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
const CXXNullPtrLiteralExpr *E) {
if (DiscardResult)
return true;
@@ -3642,7 +3627,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
+bool Compiler<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
if (DiscardResult)
return true;
@@ -3653,7 +3638,7 @@ bool ByteCodeExprGen<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
+bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
if (DiscardResult)
return true;
@@ -3666,8 +3651,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
return this->emitThis(E);
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitStmt(const Stmt *S) {
+template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {
switch (S->getStmtClass()) {
case Stmt::CompoundStmtClass:
return visitCompoundStmt(cast<CompoundStmt>(S));
@@ -3718,8 +3702,7 @@ bool ByteCodeExprGen<Emitter>::visitStmt(const Stmt *S) {
/// Visits the given statment without creating a variable
/// scope for it in case it is a compound statement.
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitLoopBody(const Stmt *S) {
+template <class Emitter> bool Compiler<Emitter>::visitLoopBody(const Stmt *S) {
if (isa<NullStmt>(S))
return true;
@@ -3734,7 +3717,7 @@ bool ByteCodeExprGen<Emitter>::visitLoopBody(const Stmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
+bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
BlockScope<Emitter> Scope(this);
for (auto *InnerStmt : S->body())
if (!visitStmt(InnerStmt))
@@ -3743,7 +3726,7 @@ bool ByteCodeExprGen<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
+bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS) {
for (auto *D : DS->decls()) {
if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl,
FunctionDecl>(D))
@@ -3760,7 +3743,7 @@ bool ByteCodeExprGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
+bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
if (const Expr *RE = RS->getRetValue()) {
ExprScope<Emitter> RetScope(this);
if (ReturnType) {
@@ -3791,8 +3774,7 @@ bool ByteCodeExprGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
return this->emitRetVoid(RS);
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitIfStmt(const IfStmt *IS) {
+template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
BlockScope<Emitter> IfScope(this);
if (IS->isNonNegatedConsteval())
@@ -3837,7 +3819,7 @@ bool ByteCodeExprGen<Emitter>::visitIfStmt(const IfStmt *IS) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
+bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
const Expr *Cond = S->getCond();
const Stmt *Body = S->getBody();
@@ -3870,8 +3852,7 @@ bool ByteCodeExprGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
return true;
}
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitDoStmt(const DoStmt *S) {
+template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
const Expr *Cond = S->getCond();
const Stmt *Body = S->getBody();
@@ -3899,7 +3880,7 @@ bool ByteCodeExprGen<Emitter>::visitDoStmt(const DoStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitForStmt(const ForStmt *S) {
+bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
// for (Init; Cond; Inc) { Body }
const Stmt *Init = S->getInit();
const Expr *Cond = S->getCond();
@@ -3944,7 +3925,7 @@ bool ByteCodeExprGen<Emitter>::visitForStmt(const ForStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
+bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
const Stmt *Init = S->getInit();
const Expr *Cond = S->getCond();
const Expr *Inc = S->getInc();
@@ -3998,7 +3979,7 @@ bool ByteCodeExprGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
+bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
if (!BreakLabel)
return false;
@@ -4007,7 +3988,7 @@ bool ByteCodeExprGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
+bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
if (!ContinueLabel)
return false;
@@ -4016,7 +3997,7 @@ bool ByteCodeExprGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
+bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
const Expr *Cond = S->getCond();
PrimType CondT = this->classifyPrim(Cond->getType());
@@ -4086,19 +4067,19 @@ bool ByteCodeExprGen<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitCaseStmt(const CaseStmt *S) {
+bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
this->emitLabel(CaseLabels[S]);
return this->visitStmt(S->getSubStmt());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
+bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
this->emitLabel(*DefaultLabel);
return this->visitStmt(S->getSubStmt());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
+bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
if (this->Ctx.getLangOpts().CXXAssumptions &&
!this->Ctx.getLangOpts().MSVCCompat) {
for (const Attr *A : S->getAttrs()) {
@@ -4129,14 +4110,13 @@ bool ByteCodeExprGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
+bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
// Ignore all handlers.
return this->visitStmt(S->getTryBlock());
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitLambdaStaticInvokerBody(
- const CXXMethodDecl *MD) {
+bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
assert(MD->isLambdaStaticInvoker());
assert(MD->hasBody());
assert(cast<CompoundStmt>(MD->getBody())->body_empty());
@@ -4186,8 +4166,7 @@ bool ByteCodeExprGen<Emitter>::emitLambdaStaticInvokerBody(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitFunc(const FunctionDecl *F) {
-
+bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
// Classify the return type.
ReturnType = this->classify(F->getReturnType());
@@ -4303,7 +4282,7 @@ bool ByteCodeExprGen<Emitter>::visitFunc(const FunctionDecl *F) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
+bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
if (SubExpr->getType()->isAnyComplexType())
return this->VisitComplexUnaryOperator(E);
@@ -4463,7 +4442,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
if (!this->visit(SubExpr))
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
- case UO_Plus: // +x
+ case UO_Plus: // +x
if (!this->visit(SubExpr)) // noop
return false;
return DiscardResult ? this->emitPop(*T, E) : true;
@@ -4475,11 +4454,11 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
}
// We should already have a pointer when we get here.
return this->delegate(SubExpr);
- case UO_Deref: // *x
+ case UO_Deref: // *x
if (DiscardResult)
return this->discard(SubExpr);
return this->visit(SubExpr);
- case UO_Not: // ~x
+ case UO_Not: // ~x
if (!this->visit(SubExpr))
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
@@ -4502,8 +4481,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
- const UnaryOperator *E) {
+bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
assert(SubExpr->getType()->isAnyComplexType());
@@ -4610,7 +4588,7 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
+bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (DiscardResult)
return true;
@@ -4733,20 +4711,19 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
+bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
const auto *D = E->getDecl();
return this->visitDeclRef(D, E);
}
-template <class Emitter>
-void ByteCodeExprGen<Emitter>::emitCleanup() {
+template <class Emitter> void Compiler<Emitter>::emitCleanup() {
for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
C->emitDestruction();
}
template <class Emitter>
unsigned
-ByteCodeExprGen<Emitter>::collectBaseOffset(const QualType BaseType,
+Compiler<Emitter>::collectBaseOffset(const QualType BaseType,
const QualType DerivedType) {
const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
if (const auto *PT = dyn_cast<PointerType>(Ty))
@@ -4761,8 +4738,8 @@ ByteCodeExprGen<Emitter>::collectBaseOffset(const QualType BaseType,
/// Emit casts from a PrimType to another PrimType.
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
- QualType ToQT, const Expr *E) {
+bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
+ QualType ToQT, const Expr *E) {
if (FromT == PT_Float) {
// Floating to floating.
@@ -4804,7 +4781,7 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
/// Emits __real(SubExpr)
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
+bool Compiler<Emitter>::emitComplexReal(const Expr *SubExpr) {
assert(SubExpr->getType()->isAnyComplexType());
if (DiscardResult)
@@ -4824,7 +4801,7 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) {
+bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
assert(!DiscardResult);
PrimType ElemT = classifyComplexElementType(E->getType());
// We emit the expression (__real(E) != 0 || __imag(E) != 0)
@@ -4870,9 +4847,8 @@ bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitComplexComparison(const Expr *LHS,
- const Expr *RHS,
- const BinaryOperator *E) {
+bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
+ const BinaryOperator *E) {
assert(E->isComparisonOp());
assert(!Initializing);
assert(!DiscardResult);
@@ -4969,7 +4945,7 @@ bool ByteCodeExprGen<Emitter>::emitComplexComparison(const Expr *LHS,
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
+bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
assert(R);
// First, destroy all fields.
for (const Record::Field &Field : llvm::reverse(R->fields())) {
@@ -5017,7 +4993,7 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::emitDestruction(const Descriptor *Desc) {
+bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
assert(Desc);
assert(!Desc->isPrimitive());
assert(!Desc->isPrimitiveArray());
@@ -5060,8 +5036,8 @@ bool ByteCodeExprGen<Emitter>::emitDestruction(const Descriptor *Desc) {
namespace clang {
namespace interp {
-template class ByteCodeExprGen<ByteCodeEmitter>;
-template class ByteCodeExprGen<EvalEmitter>;
+template class Compiler<ByteCodeEmitter>;
+template class Compiler<EvalEmitter>;
} // namespace interp
} // namespace clang
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/Compiler.h
similarity index 94%
rename from clang/lib/AST/Interp/ByteCodeExprGen.h
rename to clang/lib/AST/Interp/Compiler.h
index 40955dd43a907..cdc416b569500 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -1,4 +1,4 @@
-//===--- ByteCodeExprGen.h - Code generator for expressions -----*- C++ -*-===//
+//===--- Compiler.h - Code generator for expressions -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -41,8 +41,8 @@ template <class Emitter> class SwitchScope;
/// Compilation context for expressions.
template <class Emitter>
-class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
- public Emitter {
+class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
+ public Emitter {
protected:
// Aliases for types defined in the emitter.
using LabelTy = typename Emitter::LabelTy;
@@ -58,7 +58,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
public:
/// Initializes the compiler and the backend emitter.
template <typename... Tys>
- ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
+ Compiler(Context &Ctx, Program &P, Tys &&...Args)
: Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
// Expressions.
@@ -369,13 +369,13 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
OptLabelTy DefaultLabel;
};
-extern template class ByteCodeExprGen<ByteCodeEmitter>;
-extern template class ByteCodeExprGen<EvalEmitter>;
+extern template class Compiler<ByteCodeEmitter>;
+extern template class Compiler<EvalEmitter>;
/// Scope chain managing the variable lifetimes.
template <class Emitter> class VariableScope {
public:
- VariableScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
+ VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD) {
Ctx->VarScope = this;
}
@@ -422,8 +422,8 @@ template <class Emitter> class VariableScope {
VariableScope *getParent() const { return Parent; }
protected:
- /// ByteCodeExprGen instance.
- ByteCodeExprGen<Emitter> *Ctx;
+ /// Compiler instance.
+ Compiler<Emitter> *Ctx;
/// Link to the parent scope.
VariableScope *Parent;
const ValueDecl *ValDecl = nullptr;
@@ -432,7 +432,7 @@ template <class Emitter> class VariableScope {
/// Generic scope for local variables.
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
public:
- LocalScope(ByteCodeExprGen<Emitter> *Ctx)
+ LocalScope(Compiler<Emitter> *Ctx)
: VariableScope<Emitter>(Ctx, nullptr) {}
/// Emit a Destroy op for this scope.
@@ -527,8 +527,7 @@ template <class Emitter> class DestructorScope final {
/// variables are automatically emitted when the AutoScope is destroyed.
template <class Emitter> class AutoScope : public LocalScope<Emitter> {
public:
- AutoScope(ByteCodeExprGen<Emitter> *Ctx)
- : LocalScope<Emitter>(Ctx), DS(*this) {}
+ AutoScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx), DS(*this) {}
private:
DestructorScope<Emitter> DS;
@@ -537,7 +536,7 @@ template <class Emitter> class AutoScope : public LocalScope<Emitter> {
/// Scope for storage declared in a compound statement.
template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
public:
- BlockScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
+ BlockScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
void addExtended(const Scope::Local &Local) override {
// If we to this point, just add the variable as a normal local
@@ -549,12 +548,12 @@ template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
public:
- ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
+ ExprScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
};
template <class Emitter> class ArrayIndexScope final {
public:
- ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
+ ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
OldArrayIndex = Ctx->ArrayIndex;
Ctx->ArrayIndex = Index;
}
@@ -562,14 +561,13 @@ template <class Emitter> class ArrayIndexScope final {
~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
private:
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
std::optional<uint64_t> OldArrayIndex;
};
template <class Emitter> class SourceLocScope final {
public:
- SourceLocScope(ByteCodeExprGen<Emitter> *Ctx, const Expr *DefaultExpr)
- : Ctx(Ctx) {
+ SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
assert(DefaultExpr);
// We only switch if the current SourceLocDefaultExpr is null.
if (!Ctx->SourceLocDefaultExpr) {
@@ -584,7 +582,7 @@ template <class Emitter> class SourceLocScope final {
}
private:
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
bool Enabled = false;
};
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 338165e03586a..22ccae4fa30f8 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -8,7 +8,7 @@
#include "Context.h"
#include "ByteCodeEmitter.h"
-#include "ByteCodeExprGen.h"
+#include "Compiler.h"
#include "EvalEmitter.h"
#include "Interp.h"
#include "InterpFrame.h"
@@ -29,7 +29,7 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
assert(Stk.empty());
Function *Func = P->getFunction(FD);
if (!Func || !Func->hasBody())
- Func = ByteCodeExprGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
+ Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD);
APValue DummyResult;
if (!Run(Parent, Func, DummyResult))
@@ -40,7 +40,7 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
bool Recursing = !Stk.empty();
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
@@ -66,7 +66,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
bool Recursing = !Stk.empty();
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
@@ -91,7 +91,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
APValue &Result) {
bool Recursing = !Stk.empty();
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
bool CheckGlobalInitialized =
shouldBeGloballyIndexed(VD) &&
@@ -260,7 +260,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
return Func;
if (!Func || WasNotDefined) {
- if (auto F = ByteCodeExprGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
+ if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}
>From 8da09ef0e9ff71d84333f420ae1df1bd016aedc9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 2 Mar 2024 17:25:45 +0100
Subject: [PATCH 3/3] [clang][Interp] Implement StmtExprs
---
clang/lib/AST/Interp/Compiler.cpp | 26 ++++++++++++++++++++++++++
clang/lib/AST/Interp/Compiler.h | 1 +
clang/test/AST/Interp/literals.cpp | 12 ++++++++++++
3 files changed, 39 insertions(+)
diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index 4f424b2a60871..a361198182e90 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -2746,6 +2746,32 @@ bool Compiler<Emitter>::VisitConvertVectorExpr(
return true;
}
+template <class Emitter>
+bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
+ BlockScope<Emitter> BS(this);
+
+ const CompoundStmt *CS = E->getSubStmt();
+ const Stmt *Result = CS->getStmtExprResult();
+ for (const Stmt *S : CS->body()) {
+ if (S != Result) {
+ if (!this->visitStmt(S))
+ return false;
+ continue;
+ }
+
+ assert(S == Result);
+ // This better produces a value (i.e. is an expression).
+ if (const Expr *ResultExpr = dyn_cast<Expr>(S)) {
+ if (DiscardResult)
+ return this->discard(ResultExpr);
+ return this->delegate(ResultExpr);
+ }
+ return false;
+ }
+
+ return true;
+}
+
template <class Emitter>
bool Compiler<Emitter>::VisitShuffleVectorExpr(
const ShuffleVectorExpr *E) {
diff --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index cdc416b569500..797580837515d 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -134,6 +134,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
+ bool VisitStmtExpr(const StmtExpr *E);
// Statements.
bool visitCompoundStmt(const CompoundStmt *S);
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 5a29013a053a2..9a8eb1e44ce54 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1211,6 +1211,18 @@ constexpr int externvar1() { // both-error {{never produces a constant expressio
return arr[0]; // ref-note {{read of non-constexpr variable 'arr'}} \
// expected-note {{indexing of array without known bound}}
}
+
+namespace StmtExprs {
+ constexpr int foo() {
+ ({
+ int i;
+ for (i = 0; i < 76; i++) {}
+ i; // both-warning {{expression result unused}}
+ });
+ return 76;
+ }
+ static_assert(foo() == 76, "");
+}
#endif
namespace Extern {
More information about the cfe-commits
mailing list