1 1.1 joerg //===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===// 2 1.1 joerg // 3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 joerg // 7 1.1 joerg //===----------------------------------------------------------------------===// 8 1.1 joerg 9 1.1 joerg #include "ByteCodeStmtGen.h" 10 1.1 joerg #include "ByteCodeEmitter.h" 11 1.1 joerg #include "ByteCodeGenError.h" 12 1.1 joerg #include "Context.h" 13 1.1 joerg #include "Function.h" 14 1.1 joerg #include "PrimType.h" 15 1.1 joerg #include "Program.h" 16 1.1 joerg #include "State.h" 17 1.1.1.2 joerg #include "clang/Basic/LLVM.h" 18 1.1 joerg 19 1.1 joerg using namespace clang; 20 1.1 joerg using namespace clang::interp; 21 1.1 joerg 22 1.1 joerg namespace clang { 23 1.1 joerg namespace interp { 24 1.1 joerg 25 1.1 joerg /// Scope managing label targets. 26 1.1 joerg template <class Emitter> class LabelScope { 27 1.1 joerg public: 28 1.1 joerg virtual ~LabelScope() { } 29 1.1 joerg 30 1.1 joerg protected: 31 1.1 joerg LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {} 32 1.1 joerg /// ByteCodeStmtGen instance. 33 1.1 joerg ByteCodeStmtGen<Emitter> *Ctx; 34 1.1 joerg }; 35 1.1 joerg 36 1.1 joerg /// Sets the context for break/continue statements. 37 1.1 joerg template <class Emitter> class LoopScope final : public LabelScope<Emitter> { 38 1.1 joerg public: 39 1.1 joerg using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy; 40 1.1 joerg using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy; 41 1.1 joerg 42 1.1 joerg LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel, 43 1.1 joerg LabelTy ContinueLabel) 44 1.1 joerg : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), 45 1.1 joerg OldContinueLabel(Ctx->ContinueLabel) { 46 1.1 joerg this->Ctx->BreakLabel = BreakLabel; 47 1.1 joerg this->Ctx->ContinueLabel = ContinueLabel; 48 1.1 joerg } 49 1.1 joerg 50 1.1 joerg ~LoopScope() { 51 1.1 joerg this->Ctx->BreakLabel = OldBreakLabel; 52 1.1 joerg this->Ctx->ContinueLabel = OldContinueLabel; 53 1.1 joerg } 54 1.1 joerg 55 1.1 joerg private: 56 1.1 joerg OptLabelTy OldBreakLabel; 57 1.1 joerg OptLabelTy OldContinueLabel; 58 1.1 joerg }; 59 1.1 joerg 60 1.1 joerg // Sets the context for a switch scope, mapping labels. 61 1.1 joerg template <class Emitter> class SwitchScope final : public LabelScope<Emitter> { 62 1.1 joerg public: 63 1.1 joerg using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy; 64 1.1 joerg using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy; 65 1.1 joerg using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap; 66 1.1 joerg 67 1.1 joerg SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels, 68 1.1 joerg LabelTy BreakLabel, OptLabelTy DefaultLabel) 69 1.1 joerg : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), 70 1.1 joerg OldDefaultLabel(this->Ctx->DefaultLabel), 71 1.1 joerg OldCaseLabels(std::move(this->Ctx->CaseLabels)) { 72 1.1 joerg this->Ctx->BreakLabel = BreakLabel; 73 1.1 joerg this->Ctx->DefaultLabel = DefaultLabel; 74 1.1 joerg this->Ctx->CaseLabels = std::move(CaseLabels); 75 1.1 joerg } 76 1.1 joerg 77 1.1 joerg ~SwitchScope() { 78 1.1 joerg this->Ctx->BreakLabel = OldBreakLabel; 79 1.1 joerg this->Ctx->DefaultLabel = OldDefaultLabel; 80 1.1 joerg this->Ctx->CaseLabels = std::move(OldCaseLabels); 81 1.1 joerg } 82 1.1 joerg 83 1.1 joerg private: 84 1.1 joerg OptLabelTy OldBreakLabel; 85 1.1 joerg OptLabelTy OldDefaultLabel; 86 1.1 joerg CaseMap OldCaseLabels; 87 1.1 joerg }; 88 1.1 joerg 89 1.1 joerg } // namespace interp 90 1.1 joerg } // namespace clang 91 1.1 joerg 92 1.1 joerg template <class Emitter> 93 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) { 94 1.1 joerg // Classify the return type. 95 1.1 joerg ReturnType = this->classify(F->getReturnType()); 96 1.1 joerg 97 1.1 joerg // Set up fields and context if a constructor. 98 1.1 joerg if (auto *MD = dyn_cast<CXXMethodDecl>(F)) 99 1.1 joerg return this->bail(MD); 100 1.1 joerg 101 1.1 joerg if (auto *Body = F->getBody()) 102 1.1 joerg if (!visitStmt(Body)) 103 1.1 joerg return false; 104 1.1 joerg 105 1.1 joerg // Emit a guard return to protect against a code path missing one. 106 1.1 joerg if (F->getReturnType()->isVoidType()) 107 1.1 joerg return this->emitRetVoid(SourceInfo{}); 108 1.1 joerg else 109 1.1 joerg return this->emitNoRet(SourceInfo{}); 110 1.1 joerg } 111 1.1 joerg 112 1.1 joerg template <class Emitter> 113 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) { 114 1.1 joerg switch (S->getStmtClass()) { 115 1.1 joerg case Stmt::CompoundStmtClass: 116 1.1 joerg return visitCompoundStmt(cast<CompoundStmt>(S)); 117 1.1 joerg case Stmt::DeclStmtClass: 118 1.1 joerg return visitDeclStmt(cast<DeclStmt>(S)); 119 1.1 joerg case Stmt::ReturnStmtClass: 120 1.1 joerg return visitReturnStmt(cast<ReturnStmt>(S)); 121 1.1 joerg case Stmt::IfStmtClass: 122 1.1 joerg return visitIfStmt(cast<IfStmt>(S)); 123 1.1 joerg case Stmt::NullStmtClass: 124 1.1 joerg return true; 125 1.1 joerg default: { 126 1.1 joerg if (auto *Exp = dyn_cast<Expr>(S)) 127 1.1 joerg return this->discard(Exp); 128 1.1 joerg return this->bail(S); 129 1.1 joerg } 130 1.1 joerg } 131 1.1 joerg } 132 1.1 joerg 133 1.1 joerg template <class Emitter> 134 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitCompoundStmt( 135 1.1 joerg const CompoundStmt *CompoundStmt) { 136 1.1 joerg BlockScope<Emitter> Scope(this); 137 1.1 joerg for (auto *InnerStmt : CompoundStmt->body()) 138 1.1 joerg if (!visitStmt(InnerStmt)) 139 1.1 joerg return false; 140 1.1 joerg return true; 141 1.1 joerg } 142 1.1 joerg 143 1.1 joerg template <class Emitter> 144 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) { 145 1.1 joerg for (auto *D : DS->decls()) { 146 1.1 joerg // Variable declarator. 147 1.1 joerg if (auto *VD = dyn_cast<VarDecl>(D)) { 148 1.1 joerg if (!visitVarDecl(VD)) 149 1.1 joerg return false; 150 1.1 joerg continue; 151 1.1 joerg } 152 1.1 joerg 153 1.1 joerg // Decomposition declarator. 154 1.1 joerg if (auto *DD = dyn_cast<DecompositionDecl>(D)) { 155 1.1 joerg return this->bail(DD); 156 1.1 joerg } 157 1.1 joerg } 158 1.1 joerg 159 1.1 joerg return true; 160 1.1 joerg } 161 1.1 joerg 162 1.1 joerg template <class Emitter> 163 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) { 164 1.1 joerg if (const Expr *RE = RS->getRetValue()) { 165 1.1 joerg ExprScope<Emitter> RetScope(this); 166 1.1 joerg if (ReturnType) { 167 1.1 joerg // Primitive types are simply returned. 168 1.1 joerg if (!this->visit(RE)) 169 1.1 joerg return false; 170 1.1 joerg this->emitCleanup(); 171 1.1 joerg return this->emitRet(*ReturnType, RS); 172 1.1 joerg } else { 173 1.1 joerg // RVO - construct the value in the return location. 174 1.1 joerg auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); }; 175 1.1 joerg if (!this->visitInitializer(RE, ReturnLocation)) 176 1.1 joerg return false; 177 1.1 joerg this->emitCleanup(); 178 1.1 joerg return this->emitRetVoid(RS); 179 1.1 joerg } 180 1.1 joerg } else { 181 1.1 joerg this->emitCleanup(); 182 1.1 joerg if (!this->emitRetVoid(RS)) 183 1.1 joerg return false; 184 1.1 joerg return true; 185 1.1 joerg } 186 1.1 joerg } 187 1.1 joerg 188 1.1 joerg template <class Emitter> 189 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) { 190 1.1 joerg BlockScope<Emitter> IfScope(this); 191 1.1 joerg if (auto *CondInit = IS->getInit()) 192 1.1 joerg if (!visitStmt(IS->getInit())) 193 1.1 joerg return false; 194 1.1 joerg 195 1.1 joerg if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt()) 196 1.1 joerg if (!visitDeclStmt(CondDecl)) 197 1.1 joerg return false; 198 1.1 joerg 199 1.1 joerg if (!this->visitBool(IS->getCond())) 200 1.1 joerg return false; 201 1.1 joerg 202 1.1 joerg if (const Stmt *Else = IS->getElse()) { 203 1.1 joerg LabelTy LabelElse = this->getLabel(); 204 1.1 joerg LabelTy LabelEnd = this->getLabel(); 205 1.1 joerg if (!this->jumpFalse(LabelElse)) 206 1.1 joerg return false; 207 1.1 joerg if (!visitStmt(IS->getThen())) 208 1.1 joerg return false; 209 1.1 joerg if (!this->jump(LabelEnd)) 210 1.1 joerg return false; 211 1.1 joerg this->emitLabel(LabelElse); 212 1.1 joerg if (!visitStmt(Else)) 213 1.1 joerg return false; 214 1.1 joerg this->emitLabel(LabelEnd); 215 1.1 joerg } else { 216 1.1 joerg LabelTy LabelEnd = this->getLabel(); 217 1.1 joerg if (!this->jumpFalse(LabelEnd)) 218 1.1 joerg return false; 219 1.1 joerg if (!visitStmt(IS->getThen())) 220 1.1 joerg return false; 221 1.1 joerg this->emitLabel(LabelEnd); 222 1.1 joerg } 223 1.1 joerg 224 1.1 joerg return true; 225 1.1 joerg } 226 1.1 joerg 227 1.1 joerg template <class Emitter> 228 1.1 joerg bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) { 229 1.1 joerg auto DT = VD->getType(); 230 1.1 joerg 231 1.1 joerg if (!VD->hasLocalStorage()) { 232 1.1 joerg // No code generation required. 233 1.1 joerg return true; 234 1.1 joerg } 235 1.1 joerg 236 1.1 joerg // Integers, pointers, primitives. 237 1.1 joerg if (Optional<PrimType> T = this->classify(DT)) { 238 1.1 joerg auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified()); 239 1.1 joerg // Compile the initialiser in its own scope. 240 1.1 joerg { 241 1.1 joerg ExprScope<Emitter> Scope(this); 242 1.1 joerg if (!this->visit(VD->getInit())) 243 1.1 joerg return false; 244 1.1 joerg } 245 1.1 joerg // Set the value. 246 1.1 joerg return this->emitSetLocal(*T, Off, VD); 247 1.1 joerg } else { 248 1.1 joerg // Composite types - allocate storage and initialize it. 249 1.1 joerg if (auto Off = this->allocateLocal(VD)) { 250 1.1 joerg return this->visitLocalInitializer(VD->getInit(), *Off); 251 1.1 joerg } else { 252 1.1 joerg return this->bail(VD); 253 1.1 joerg } 254 1.1 joerg } 255 1.1 joerg } 256 1.1 joerg 257 1.1 joerg namespace clang { 258 1.1 joerg namespace interp { 259 1.1 joerg 260 1.1 joerg template class ByteCodeStmtGen<ByteCodeEmitter>; 261 1.1 joerg 262 1.1 joerg } // namespace interp 263 1.1 joerg } // namespace clang 264