17330f729Sjoerg //===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "ByteCodeStmtGen.h"
107330f729Sjoerg #include "ByteCodeEmitter.h"
117330f729Sjoerg #include "ByteCodeGenError.h"
127330f729Sjoerg #include "Context.h"
137330f729Sjoerg #include "Function.h"
147330f729Sjoerg #include "PrimType.h"
157330f729Sjoerg #include "Program.h"
167330f729Sjoerg #include "State.h"
17*e038c9c4Sjoerg #include "clang/Basic/LLVM.h"
187330f729Sjoerg
197330f729Sjoerg using namespace clang;
207330f729Sjoerg using namespace clang::interp;
217330f729Sjoerg
227330f729Sjoerg namespace clang {
237330f729Sjoerg namespace interp {
247330f729Sjoerg
257330f729Sjoerg /// Scope managing label targets.
267330f729Sjoerg template <class Emitter> class LabelScope {
277330f729Sjoerg public:
~LabelScope()287330f729Sjoerg virtual ~LabelScope() { }
297330f729Sjoerg
307330f729Sjoerg protected:
LabelScope(ByteCodeStmtGen<Emitter> * Ctx)317330f729Sjoerg LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {}
327330f729Sjoerg /// ByteCodeStmtGen instance.
337330f729Sjoerg ByteCodeStmtGen<Emitter> *Ctx;
347330f729Sjoerg };
357330f729Sjoerg
367330f729Sjoerg /// Sets the context for break/continue statements.
377330f729Sjoerg template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
387330f729Sjoerg public:
397330f729Sjoerg using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
407330f729Sjoerg using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
417330f729Sjoerg
LoopScope(ByteCodeStmtGen<Emitter> * Ctx,LabelTy BreakLabel,LabelTy ContinueLabel)427330f729Sjoerg LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel,
437330f729Sjoerg LabelTy ContinueLabel)
447330f729Sjoerg : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
457330f729Sjoerg OldContinueLabel(Ctx->ContinueLabel) {
467330f729Sjoerg this->Ctx->BreakLabel = BreakLabel;
477330f729Sjoerg this->Ctx->ContinueLabel = ContinueLabel;
487330f729Sjoerg }
497330f729Sjoerg
~LoopScope()507330f729Sjoerg ~LoopScope() {
517330f729Sjoerg this->Ctx->BreakLabel = OldBreakLabel;
527330f729Sjoerg this->Ctx->ContinueLabel = OldContinueLabel;
537330f729Sjoerg }
547330f729Sjoerg
557330f729Sjoerg private:
567330f729Sjoerg OptLabelTy OldBreakLabel;
577330f729Sjoerg OptLabelTy OldContinueLabel;
587330f729Sjoerg };
597330f729Sjoerg
607330f729Sjoerg // Sets the context for a switch scope, mapping labels.
617330f729Sjoerg template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
627330f729Sjoerg public:
637330f729Sjoerg using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
647330f729Sjoerg using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
657330f729Sjoerg using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
667330f729Sjoerg
SwitchScope(ByteCodeStmtGen<Emitter> * Ctx,CaseMap && CaseLabels,LabelTy BreakLabel,OptLabelTy DefaultLabel)677330f729Sjoerg SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels,
687330f729Sjoerg LabelTy BreakLabel, OptLabelTy DefaultLabel)
697330f729Sjoerg : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
707330f729Sjoerg OldDefaultLabel(this->Ctx->DefaultLabel),
717330f729Sjoerg OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
727330f729Sjoerg this->Ctx->BreakLabel = BreakLabel;
737330f729Sjoerg this->Ctx->DefaultLabel = DefaultLabel;
747330f729Sjoerg this->Ctx->CaseLabels = std::move(CaseLabels);
757330f729Sjoerg }
767330f729Sjoerg
~SwitchScope()777330f729Sjoerg ~SwitchScope() {
787330f729Sjoerg this->Ctx->BreakLabel = OldBreakLabel;
797330f729Sjoerg this->Ctx->DefaultLabel = OldDefaultLabel;
807330f729Sjoerg this->Ctx->CaseLabels = std::move(OldCaseLabels);
817330f729Sjoerg }
827330f729Sjoerg
837330f729Sjoerg private:
847330f729Sjoerg OptLabelTy OldBreakLabel;
857330f729Sjoerg OptLabelTy OldDefaultLabel;
867330f729Sjoerg CaseMap OldCaseLabels;
877330f729Sjoerg };
887330f729Sjoerg
897330f729Sjoerg } // namespace interp
907330f729Sjoerg } // namespace clang
917330f729Sjoerg
927330f729Sjoerg template <class Emitter>
visitFunc(const FunctionDecl * F)937330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
947330f729Sjoerg // Classify the return type.
957330f729Sjoerg ReturnType = this->classify(F->getReturnType());
967330f729Sjoerg
977330f729Sjoerg // Set up fields and context if a constructor.
987330f729Sjoerg if (auto *MD = dyn_cast<CXXMethodDecl>(F))
997330f729Sjoerg return this->bail(MD);
1007330f729Sjoerg
1017330f729Sjoerg if (auto *Body = F->getBody())
1027330f729Sjoerg if (!visitStmt(Body))
1037330f729Sjoerg return false;
1047330f729Sjoerg
1057330f729Sjoerg // Emit a guard return to protect against a code path missing one.
1067330f729Sjoerg if (F->getReturnType()->isVoidType())
1077330f729Sjoerg return this->emitRetVoid(SourceInfo{});
1087330f729Sjoerg else
1097330f729Sjoerg return this->emitNoRet(SourceInfo{});
1107330f729Sjoerg }
1117330f729Sjoerg
1127330f729Sjoerg template <class Emitter>
visitStmt(const Stmt * S)1137330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
1147330f729Sjoerg switch (S->getStmtClass()) {
1157330f729Sjoerg case Stmt::CompoundStmtClass:
1167330f729Sjoerg return visitCompoundStmt(cast<CompoundStmt>(S));
1177330f729Sjoerg case Stmt::DeclStmtClass:
1187330f729Sjoerg return visitDeclStmt(cast<DeclStmt>(S));
1197330f729Sjoerg case Stmt::ReturnStmtClass:
1207330f729Sjoerg return visitReturnStmt(cast<ReturnStmt>(S));
1217330f729Sjoerg case Stmt::IfStmtClass:
1227330f729Sjoerg return visitIfStmt(cast<IfStmt>(S));
1237330f729Sjoerg case Stmt::NullStmtClass:
1247330f729Sjoerg return true;
1257330f729Sjoerg default: {
1267330f729Sjoerg if (auto *Exp = dyn_cast<Expr>(S))
1277330f729Sjoerg return this->discard(Exp);
1287330f729Sjoerg return this->bail(S);
1297330f729Sjoerg }
1307330f729Sjoerg }
1317330f729Sjoerg }
1327330f729Sjoerg
1337330f729Sjoerg template <class Emitter>
visitCompoundStmt(const CompoundStmt * CompoundStmt)1347330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
1357330f729Sjoerg const CompoundStmt *CompoundStmt) {
1367330f729Sjoerg BlockScope<Emitter> Scope(this);
1377330f729Sjoerg for (auto *InnerStmt : CompoundStmt->body())
1387330f729Sjoerg if (!visitStmt(InnerStmt))
1397330f729Sjoerg return false;
1407330f729Sjoerg return true;
1417330f729Sjoerg }
1427330f729Sjoerg
1437330f729Sjoerg template <class Emitter>
visitDeclStmt(const DeclStmt * DS)1447330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
1457330f729Sjoerg for (auto *D : DS->decls()) {
1467330f729Sjoerg // Variable declarator.
1477330f729Sjoerg if (auto *VD = dyn_cast<VarDecl>(D)) {
1487330f729Sjoerg if (!visitVarDecl(VD))
1497330f729Sjoerg return false;
1507330f729Sjoerg continue;
1517330f729Sjoerg }
1527330f729Sjoerg
1537330f729Sjoerg // Decomposition declarator.
1547330f729Sjoerg if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
1557330f729Sjoerg return this->bail(DD);
1567330f729Sjoerg }
1577330f729Sjoerg }
1587330f729Sjoerg
1597330f729Sjoerg return true;
1607330f729Sjoerg }
1617330f729Sjoerg
1627330f729Sjoerg template <class Emitter>
visitReturnStmt(const ReturnStmt * RS)1637330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
1647330f729Sjoerg if (const Expr *RE = RS->getRetValue()) {
1657330f729Sjoerg ExprScope<Emitter> RetScope(this);
1667330f729Sjoerg if (ReturnType) {
1677330f729Sjoerg // Primitive types are simply returned.
1687330f729Sjoerg if (!this->visit(RE))
1697330f729Sjoerg return false;
1707330f729Sjoerg this->emitCleanup();
1717330f729Sjoerg return this->emitRet(*ReturnType, RS);
1727330f729Sjoerg } else {
1737330f729Sjoerg // RVO - construct the value in the return location.
1747330f729Sjoerg auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); };
1757330f729Sjoerg if (!this->visitInitializer(RE, ReturnLocation))
1767330f729Sjoerg return false;
1777330f729Sjoerg this->emitCleanup();
1787330f729Sjoerg return this->emitRetVoid(RS);
1797330f729Sjoerg }
1807330f729Sjoerg } else {
1817330f729Sjoerg this->emitCleanup();
1827330f729Sjoerg if (!this->emitRetVoid(RS))
1837330f729Sjoerg return false;
1847330f729Sjoerg return true;
1857330f729Sjoerg }
1867330f729Sjoerg }
1877330f729Sjoerg
1887330f729Sjoerg template <class Emitter>
visitIfStmt(const IfStmt * IS)1897330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
1907330f729Sjoerg BlockScope<Emitter> IfScope(this);
1917330f729Sjoerg if (auto *CondInit = IS->getInit())
1927330f729Sjoerg if (!visitStmt(IS->getInit()))
1937330f729Sjoerg return false;
1947330f729Sjoerg
1957330f729Sjoerg if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
1967330f729Sjoerg if (!visitDeclStmt(CondDecl))
1977330f729Sjoerg return false;
1987330f729Sjoerg
1997330f729Sjoerg if (!this->visitBool(IS->getCond()))
2007330f729Sjoerg return false;
2017330f729Sjoerg
2027330f729Sjoerg if (const Stmt *Else = IS->getElse()) {
2037330f729Sjoerg LabelTy LabelElse = this->getLabel();
2047330f729Sjoerg LabelTy LabelEnd = this->getLabel();
2057330f729Sjoerg if (!this->jumpFalse(LabelElse))
2067330f729Sjoerg return false;
2077330f729Sjoerg if (!visitStmt(IS->getThen()))
2087330f729Sjoerg return false;
2097330f729Sjoerg if (!this->jump(LabelEnd))
2107330f729Sjoerg return false;
2117330f729Sjoerg this->emitLabel(LabelElse);
2127330f729Sjoerg if (!visitStmt(Else))
2137330f729Sjoerg return false;
2147330f729Sjoerg this->emitLabel(LabelEnd);
2157330f729Sjoerg } else {
2167330f729Sjoerg LabelTy LabelEnd = this->getLabel();
2177330f729Sjoerg if (!this->jumpFalse(LabelEnd))
2187330f729Sjoerg return false;
2197330f729Sjoerg if (!visitStmt(IS->getThen()))
2207330f729Sjoerg return false;
2217330f729Sjoerg this->emitLabel(LabelEnd);
2227330f729Sjoerg }
2237330f729Sjoerg
2247330f729Sjoerg return true;
2257330f729Sjoerg }
2267330f729Sjoerg
2277330f729Sjoerg template <class Emitter>
visitVarDecl(const VarDecl * VD)2287330f729Sjoerg bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) {
2297330f729Sjoerg auto DT = VD->getType();
2307330f729Sjoerg
2317330f729Sjoerg if (!VD->hasLocalStorage()) {
2327330f729Sjoerg // No code generation required.
2337330f729Sjoerg return true;
2347330f729Sjoerg }
2357330f729Sjoerg
2367330f729Sjoerg // Integers, pointers, primitives.
2377330f729Sjoerg if (Optional<PrimType> T = this->classify(DT)) {
2387330f729Sjoerg auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified());
2397330f729Sjoerg // Compile the initialiser in its own scope.
2407330f729Sjoerg {
2417330f729Sjoerg ExprScope<Emitter> Scope(this);
2427330f729Sjoerg if (!this->visit(VD->getInit()))
2437330f729Sjoerg return false;
2447330f729Sjoerg }
2457330f729Sjoerg // Set the value.
2467330f729Sjoerg return this->emitSetLocal(*T, Off, VD);
2477330f729Sjoerg } else {
2487330f729Sjoerg // Composite types - allocate storage and initialize it.
2497330f729Sjoerg if (auto Off = this->allocateLocal(VD)) {
2507330f729Sjoerg return this->visitLocalInitializer(VD->getInit(), *Off);
2517330f729Sjoerg } else {
2527330f729Sjoerg return this->bail(VD);
2537330f729Sjoerg }
2547330f729Sjoerg }
2557330f729Sjoerg }
2567330f729Sjoerg
2577330f729Sjoerg namespace clang {
2587330f729Sjoerg namespace interp {
2597330f729Sjoerg
2607330f729Sjoerg template class ByteCodeStmtGen<ByteCodeEmitter>;
2617330f729Sjoerg
2627330f729Sjoerg } // namespace interp
2637330f729Sjoerg } // namespace clang
264