diff options
Diffstat (limited to 'clang/lib/AST/Interp/ByteCodeStmtGen.cpp')
-rw-r--r-- | clang/lib/AST/Interp/ByteCodeStmtGen.cpp | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp deleted file mode 100644 index 25d9cadf6d3..00000000000 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ /dev/null @@ -1,265 +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 "ByteCodeGenError.h" -#include "Context.h" -#include "Function.h" -#include "Program.h" -#include "State.h" -#include "Type.h" - -using namespace clang; -using namespace clang::interp; - -template <typename T> using Expected = llvm::Expected<T>; -template <typename T> using Optional = llvm::Optional<T>; - -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>::visitFunc(const FunctionDecl *F) { - // Classify the return type. - ReturnType = this->classify(F->getReturnType()); - - // Set up fields and context if a constructor. - if (auto *MD = dyn_cast<CXXMethodDecl>(F)) - return this->bail(MD); - - if (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::NullStmtClass: - return true; - default: { - if (auto *Exp = dyn_cast<Expr>(S)) - return this->discard(Exp); - return this->bail(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()) { - // Variable declarator. - if (auto *VD = dyn_cast<VarDecl>(D)) { - if (!visitVarDecl(VD)) - return false; - continue; - } - - // Decomposition declarator. - if (auto *DD = dyn_cast<DecompositionDecl>(D)) { - return this->bail(DD); - } - } - - 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 { - // RVO - construct the value in the return location. - auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); }; - if (!this->visitInitializer(RE, ReturnLocation)) - return false; - this->emitCleanup(); - return this->emitRetVoid(RS); - } - } else { - this->emitCleanup(); - if (!this->emitRetVoid(RS)) - return false; - return true; - } -} - -template <class Emitter> -bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) { - BlockScope<Emitter> IfScope(this); - if (auto *CondInit = IS->getInit()) - if (!visitStmt(IS->getInit())) - 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>::visitVarDecl(const VarDecl *VD) { - auto DT = VD->getType(); - - if (!VD->hasLocalStorage()) { - // No code generation required. - return true; - } - - // Integers, pointers, primitives. - if (Optional<PrimType> T = this->classify(DT)) { - auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified()); - // Compile the initialiser in its own scope. - { - ExprScope<Emitter> Scope(this); - if (!this->visit(VD->getInit())) - return false; - } - // Set the value. - return this->emitSetLocal(*T, Off, VD); - } else { - // Composite types - allocate storage and initialize it. - if (auto Off = this->allocateLocal(VD)) { - return this->visitLocalInitializer(VD->getInit(), *Off); - } else { - return this->bail(VD); - } - } -} - -namespace clang { -namespace interp { - -template class ByteCodeStmtGen<ByteCodeEmitter>; - -} // namespace interp -} // namespace clang |