[clang] 468d668 - [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (#83683)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 27 05:43:45 PDT 2024
Author: Timm Baeder
Date: 2024-06-27T14:43:39+02:00
New Revision: 468d668c5c4031366ae38804927b450f9faf409c
URL: https://github.com/llvm/llvm-project/commit/468d668c5c4031366ae38804927b450f9faf409c
DIFF: https://github.com/llvm/llvm-project/commit/468d668c5c4031366ae38804927b450f9faf409c.diff
LOG: [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (#83683)
We currently cannot generate bytecode for statements once we've decided
we want to generate bytecode for expressions. This is a problem for `StmtExpr`, which is
an expression that requires us to evaluate a statement.
Merge ByteCodeExprGen and ByteCodeStmtGen, so we don't do that distinction anymore. Rename them to Compiler at the same time.
Added:
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
Modified:
clang/lib/AST/CMakeLists.txt
clang/lib/AST/Interp/Context.cpp
clang/lib/AST/Interp/EvalEmitter.h
clang/lib/AST/Interp/Program.cpp
Removed:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/lib/AST/Interp/ByteCodeStmtGen.h
################################################################################
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 0328666d59b1f..ceaad8d3c5a86 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -65,8 +65,7 @@ add_clang_library(clangAST
FormatString.cpp
InheritViz.cpp
Interp/ByteCodeEmitter.cpp
- Interp/ByteCodeExprGen.cpp
- Interp/ByteCodeStmtGen.cpp
+ Interp/Compiler.cpp
Interp/Context.cpp
Interp/Descriptor.cpp
Interp/Disasm.cpp
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
deleted file mode 100644
index 0618ec1aa8f58..0000000000000
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ /dev/null
@@ -1,734 +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.
- InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));
- 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;
-
- InitLinkScope<Emitter> InitScope(this, InitLink::This());
- 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/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/Compiler.cpp
similarity index 81%
rename from clang/lib/AST/Interp/ByteCodeExprGen.cpp
rename to clang/lib/AST/Interp/Compiler.cpp
index 5b06f0e0f2f05..e21e2c0eb8b6a 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,9 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "ByteCodeExprGen.h"
+#include "Compiler.h"
#include "ByteCodeEmitter.h"
-#include "ByteCodeStmtGen.h"
#include "Context.h"
#include "Floating.h"
#include "Function.h"
@@ -28,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) {
@@ -37,6 +36,10 @@ template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
Ctx->InitStack.push_back(InitLink::Decl(VD));
}
+ void addExtended(const Scope::Local &Local) override {
+ return this->addLocal(Local);
+ }
+
~DeclScope() {
this->Ctx->GlobalDecl = OldGlobalDecl;
this->Ctx->InitializingDecl = OldInitializingDecl;
@@ -53,7 +56,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) {
@@ -68,14 +71,14 @@ template <class Emitter> class OptionScope final {
private:
/// Parent context.
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
/// Old discard flag to restore.
bool OldDiscardResult;
bool OldInitializing;
};
template <class Emitter>
-bool InitLink::emit(ByteCodeExprGen<Emitter> *Ctx, const Expr *E) const {
+bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
switch (Kind) {
case K_This:
return Ctx->emitThis(E);
@@ -88,11 +91,74 @@ bool InitLink::emit(ByteCodeExprGen<Emitter> *Ctx, const Expr *E) const {
return true;
}
+/// Scope managing label targets.
+template <class Emitter> class LabelScope {
+public:
+ virtual ~LabelScope() {}
+
+protected:
+ 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 Compiler<Emitter>::LabelTy;
+ using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
+
+ LoopScope(Compiler<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 Compiler<Emitter>::LabelTy;
+ using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
+ using CaseMap = typename Compiler<Emitter>::CaseMap;
+
+ 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)) {
+ 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 ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
+bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr();
switch (CE->getCastKind()) {
@@ -546,7 +612,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;
@@ -554,7 +620,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;
@@ -562,8 +628,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;
@@ -587,12 +652,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);
@@ -764,7 +829,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();
@@ -812,7 +877,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();
@@ -873,7 +938,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);
@@ -1101,7 +1166,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))
@@ -1184,8 +1250,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();
@@ -1205,9 +1270,8 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
- const Expr *ArrayFiller,
- const Expr *E) {
+bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
+ const Expr *ArrayFiller, const Expr *E) {
if (E->getType()->isVoidType())
return this->emitInvalid(E);
@@ -1419,7 +1483,8 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
// If the initializer is of vector type itself, we have to deconstruct
// that and initialize all the target fields from the initializer fields.
if (const auto *InitVecT = Init->getType()->getAs<VectorType>()) {
- if (!this->emitCopyArray(ElemT, 0, InitIndex, InitVecT->getNumElements(), E))
+ if (!this->emitCopyArray(ElemT, 0, InitIndex,
+ InitVecT->getNumElements(), E))
return false;
InitIndex += InitVecT->getNumElements();
} else {
@@ -1447,8 +1512,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))
@@ -1468,24 +1533,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.
@@ -1501,7 +1566,7 @@ bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {
+bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {
auto It = E->begin();
return this->visit(*It);
}
@@ -1530,7 +1595,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();
@@ -1622,7 +1687,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();
@@ -1674,8 +1739,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)
@@ -1684,8 +1748,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);
@@ -1713,7 +1776,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;
@@ -1749,7 +1812,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();
@@ -1781,7 +1844,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;
@@ -1838,13 +1901,12 @@ bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCStringLiteral(
- const ObjCStringLiteral *E) {
+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);
@@ -1855,7 +1917,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;
@@ -1879,15 +1941,14 @@ bool ByteCodeExprGen<Emitter>::VisitSYCLUniqueStableNameExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
- const CharacterLiteral *E) {
+bool Compiler<Emitter>::VisitCharacterLiteral(const CharacterLiteral *E) {
if (DiscardResult)
return true;
return this->emitConst(E->getValue(), E);
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
+bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
const CompoundAssignOperator *E) {
const Expr *LHS = E->getLHS();
@@ -1961,7 +2022,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();
@@ -1998,7 +2059,7 @@ bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
+bool Compiler<Emitter>::VisitCompoundAssignOperator(
const CompoundAssignOperator *E) {
const Expr *LHS = E->getLHS();
@@ -2119,8 +2180,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();
@@ -2130,7 +2190,7 @@ bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
+bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E) {
const Expr *SubExpr = E->getSubExpr();
@@ -2202,14 +2262,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.
@@ -2274,7 +2333,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())
@@ -2283,15 +2342,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;
@@ -2330,7 +2388,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;
@@ -2338,7 +2396,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;
@@ -2346,7 +2404,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;
@@ -2355,7 +2413,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)
@@ -2364,8 +2422,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));
@@ -2477,7 +2534,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;
@@ -2533,7 +2590,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;
@@ -2568,7 +2625,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();
@@ -2627,24 +2684,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;
@@ -2652,7 +2708,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() &&
@@ -2683,14 +2739,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);
@@ -2727,7 +2782,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;
@@ -2735,7 +2790,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)
@@ -2744,14 +2799,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)) {
@@ -2775,18 +2829,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(
@@ -2796,8 +2849,7 @@ bool ByteCodeExprGen<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitConvertVectorExpr(
- const ConvertVectorExpr *E) {
+bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
assert(Initializing);
const auto *VT = E->getType()->castAs<VectorType>();
QualType ElemType = VT->getElementType();
@@ -2829,8 +2881,7 @@ bool ByteCodeExprGen<Emitter>::VisitConvertVectorExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitShuffleVectorExpr(
- const ShuffleVectorExpr *E) {
+bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
assert(Initializing);
assert(E->getNumSubExprs() > 2);
@@ -2872,7 +2923,7 @@ bool ByteCodeExprGen<Emitter>::VisitShuffleVectorExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitExtVectorElementExpr(
+bool Compiler<Emitter>::VisitExtVectorElementExpr(
const ExtVectorElementExpr *E) {
const Expr *Base = E->getBase();
assert(
@@ -2934,7 +2985,7 @@ bool ByteCodeExprGen<Emitter>::VisitExtVectorElementExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
+bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
if (!E->isExpressibleAsConstantInitializer())
return this->emitInvalid(E);
@@ -2942,7 +2993,7 @@ bool ByteCodeExprGen<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXStdInitializerListExpr(
+bool Compiler<Emitter>::VisitCXXStdInitializerListExpr(
const CXXStdInitializerListExpr *E) {
const Expr *SubExpr = E->getSubExpr();
const ConstantArrayType *ArrayType =
@@ -2974,21 +3025,23 @@ bool ByteCodeExprGen<Emitter>::VisitCXXStdInitializerListExpr(
return this->emitInitFieldPtr(R->getField(1u)->Offset, E);
}
-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;
@@ -3015,7 +3068,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())
@@ -3026,8 +3079,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.
@@ -3061,8 +3113,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);
@@ -3100,8 +3152,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
@@ -3169,7 +3221,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);
@@ -3203,13 +3255,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)
@@ -3221,15 +3273,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 *>())) {
@@ -3252,10 +3303,9 @@ unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
template <class Emitter>
std::optional<unsigned>
-ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src,
- const ValueDecl *ExtendingDecl) {
+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));
@@ -3294,31 +3344,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()) {
@@ -3360,8 +3408,7 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
/// 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,
- bool ConstantContext) {
+bool Compiler<Emitter>::visitDecl(const VarDecl *VD, bool ConstantContext) {
assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");
std::optional<PrimType> VarT = classify(VD->getType());
@@ -3434,7 +3481,7 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD,
}
template <class Emitter>
-VarCreationState ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
+VarCreationState 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;
@@ -3502,8 +3549,8 @@ VarCreationState 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);
@@ -3529,8 +3576,8 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
- const Expr *E) {
+bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
+ const Expr *E) {
if (Val.isStruct()) {
const Record *R = this->getRecord(E->getType());
@@ -3592,7 +3639,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;
@@ -3647,7 +3694,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);
@@ -3807,8 +3854,7 @@ 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);
bool Old = InitStackActive;
@@ -3819,8 +3865,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr(
}
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();
@@ -3832,8 +3877,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;
@@ -3841,7 +3885,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
}
template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
+bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
const CXXNullPtrLiteralExpr *E) {
if (DiscardResult)
return true;
@@ -3850,7 +3894,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;
@@ -3861,7 +3905,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;
@@ -3885,8 +3929,640 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
return this->emitThis(E);
}
+template <class Emitter> bool Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<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 Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
+ if (!BreakLabel)
+ return false;
+
+ this->VarScope->emitDestructors();
+ return this->jump(*BreakLabel);
+}
+
+template <class Emitter>
+bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
+ if (!ContinueLabel)
+ return false;
+
+ this->VarScope->emitDestructors();
+ return this->jump(*ContinueLabel);
+}
+
+template <class Emitter>
+bool Compiler<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 Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
+ this->emitLabel(CaseLabels[S]);
+ return this->visitStmt(S->getSubStmt());
+}
+
+template <class Emitter>
+bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
+ this->emitLabel(*DefaultLabel);
+ return this->visitStmt(S->getSubStmt());
+}
+
+template <class Emitter>
+bool Compiler<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 Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
+ // Ignore all handlers.
+ return this->visitStmt(S->getTryBlock());
+}
+
+template <class Emitter>
+bool Compiler<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 Compiler<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.
+ InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));
+ 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;
+
+ InitLinkScope<Emitter> InitScope(this, InitLink::This());
+ 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) {
+bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
if (SubExpr->getType()->isAnyComplexType())
return this->VisitComplexUnaryOperator(E);
@@ -4046,7 +4722,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;
@@ -4058,11 +4734,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);
@@ -4085,8 +4761,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());
@@ -4193,7 +4868,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;
@@ -4322,21 +4997,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,
- const QualType DerivedType) {
+unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,
+ const QualType DerivedType) {
const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
if (const auto *PT = dyn_cast<PointerType>(Ty))
return PT->getPointeeType()->getAsCXXRecordDecl();
@@ -4350,8 +5023,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.
@@ -4393,7 +5066,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)
@@ -4413,7 +5086,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)
@@ -4459,9 +5132,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);
@@ -4558,7 +5230,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())) {
@@ -4606,7 +5278,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());
@@ -4649,8 +5321,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 87%
rename from clang/lib/AST/Interp/ByteCodeExprGen.h
rename to clang/lib/AST/Interp/Compiler.h
index 88e9eddd55be4..89e36f9201a41 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.
@@ -36,8 +36,11 @@ template <class Emitter> class InitLinkScope;
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;
-template <class Emitter> class ByteCodeExprGen;
+template <class Emitter> class Compiler;
struct InitLink {
public:
enum {
@@ -60,7 +63,7 @@ struct InitLink {
InitLink(uint8_t Kind) : Kind(Kind) {}
template <class Emitter>
- bool emit(ByteCodeExprGen<Emitter> *Ctx, const Expr *E) const;
+ bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;
private:
uint32_t Kind;
@@ -84,12 +87,14 @@ struct VarCreationState {
/// 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;
using AddrTy = typename Emitter::AddrTy;
+ using OptLabelTy = std::optional<LabelTy>;
+ using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
/// Current compilation context.
Context &Ctx;
@@ -99,10 +104,10 @@ 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) {}
- // Expression visitors - result returned on interp stack.
+ // Expressions.
bool VisitCastExpr(const CastExpr *E);
bool VisitIntegerLiteral(const IntegerLiteral *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
@@ -179,9 +184,29 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *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, bool ConstantContext) override;
+ bool visitFunc(const FunctionDecl *F) override;
protected:
/// Emits scope cleanup instructions.
@@ -194,8 +219,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 {
@@ -305,6 +330,9 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
friend class ArrayIndexScope<Emitter>;
friend class SourceLocScope<Emitter>;
friend struct InitLink;
+ 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);
@@ -348,6 +376,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.
@@ -378,15 +407,28 @@ 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>;
-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;
}
@@ -433,8 +475,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;
@@ -443,8 +485,7 @@ template <class Emitter> class VariableScope {
/// Generic scope for local variables.
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
public:
- LocalScope(ByteCodeExprGen<Emitter> *Ctx)
- : VariableScope<Emitter>(Ctx, nullptr) {}
+ LocalScope(Compiler<Emitter> *Ctx) : VariableScope<Emitter>(Ctx, nullptr) {}
/// Emit a Destroy op for this scope.
~LocalScope() override {
@@ -538,8 +579,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;
@@ -548,7 +588,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
@@ -560,12 +600,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;
}
@@ -573,14 +613,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) {
@@ -595,20 +634,20 @@ template <class Emitter> class SourceLocScope final {
}
private:
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
bool Enabled = false;
};
template <class Emitter> class InitLinkScope final {
public:
- InitLinkScope(ByteCodeExprGen<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
+ InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
Ctx->InitStack.push_back(std::move(Link));
}
~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
private:
- ByteCodeExprGen<Emitter> *Ctx;
+ Compiler<Emitter> *Ctx;
};
} // namespace interp
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 98d1837204ebc..22ccae4fa30f8 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -8,8 +8,7 @@
#include "Context.h"
#include "ByteCodeEmitter.h"
-#include "ByteCodeExprGen.h"
-#include "ByteCodeStmtGen.h"
+#include "Compiler.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 = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD);
APValue DummyResult;
if (!Run(Parent, Func, DummyResult))
@@ -41,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());
@@ -67,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()) {
@@ -92,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) &&
@@ -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 = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}
diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h
index e85f37d757b69..109e6e0bc0d76 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, bool ConstantContext) = 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"
More information about the cfe-commits
mailing list