1353942Sdim//===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===// 2353942Sdim// 3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353942Sdim// See https://llvm.org/LICENSE.txt for license information. 5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353942Sdim// 7353942Sdim//===----------------------------------------------------------------------===// 8353942Sdim 9353942Sdim#include "ByteCodeStmtGen.h" 10353942Sdim#include "ByteCodeEmitter.h" 11353942Sdim#include "ByteCodeGenError.h" 12353942Sdim#include "Context.h" 13353942Sdim#include "Function.h" 14353942Sdim#include "PrimType.h" 15353942Sdim#include "Program.h" 16353942Sdim#include "State.h" 17357095Sdim#include "clang/Basic/LLVM.h" 18353942Sdim 19353942Sdimusing namespace clang; 20353942Sdimusing namespace clang::interp; 21353942Sdim 22353942Sdimnamespace clang { 23353942Sdimnamespace interp { 24353942Sdim 25353942Sdim/// Scope managing label targets. 26353942Sdimtemplate <class Emitter> class LabelScope { 27353942Sdimpublic: 28353942Sdim virtual ~LabelScope() { } 29353942Sdim 30353942Sdimprotected: 31353942Sdim LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {} 32353942Sdim /// ByteCodeStmtGen instance. 33353942Sdim ByteCodeStmtGen<Emitter> *Ctx; 34353942Sdim}; 35353942Sdim 36353942Sdim/// Sets the context for break/continue statements. 37353942Sdimtemplate <class Emitter> class LoopScope final : public LabelScope<Emitter> { 38353942Sdimpublic: 39353942Sdim using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy; 40353942Sdim using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy; 41353942Sdim 42353942Sdim LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel, 43353942Sdim LabelTy ContinueLabel) 44353942Sdim : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), 45353942Sdim OldContinueLabel(Ctx->ContinueLabel) { 46353942Sdim this->Ctx->BreakLabel = BreakLabel; 47353942Sdim this->Ctx->ContinueLabel = ContinueLabel; 48353942Sdim } 49353942Sdim 50353942Sdim ~LoopScope() { 51353942Sdim this->Ctx->BreakLabel = OldBreakLabel; 52353942Sdim this->Ctx->ContinueLabel = OldContinueLabel; 53353942Sdim } 54353942Sdim 55353942Sdimprivate: 56353942Sdim OptLabelTy OldBreakLabel; 57353942Sdim OptLabelTy OldContinueLabel; 58353942Sdim}; 59353942Sdim 60353942Sdim// Sets the context for a switch scope, mapping labels. 61353942Sdimtemplate <class Emitter> class SwitchScope final : public LabelScope<Emitter> { 62353942Sdimpublic: 63353942Sdim using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy; 64353942Sdim using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy; 65353942Sdim using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap; 66353942Sdim 67353942Sdim SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels, 68353942Sdim LabelTy BreakLabel, OptLabelTy DefaultLabel) 69353942Sdim : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), 70353942Sdim OldDefaultLabel(this->Ctx->DefaultLabel), 71353942Sdim OldCaseLabels(std::move(this->Ctx->CaseLabels)) { 72353942Sdim this->Ctx->BreakLabel = BreakLabel; 73353942Sdim this->Ctx->DefaultLabel = DefaultLabel; 74353942Sdim this->Ctx->CaseLabels = std::move(CaseLabels); 75353942Sdim } 76353942Sdim 77353942Sdim ~SwitchScope() { 78353942Sdim this->Ctx->BreakLabel = OldBreakLabel; 79353942Sdim this->Ctx->DefaultLabel = OldDefaultLabel; 80353942Sdim this->Ctx->CaseLabels = std::move(OldCaseLabels); 81353942Sdim } 82353942Sdim 83353942Sdimprivate: 84353942Sdim OptLabelTy OldBreakLabel; 85353942Sdim OptLabelTy OldDefaultLabel; 86353942Sdim CaseMap OldCaseLabels; 87353942Sdim}; 88353942Sdim 89353942Sdim} // namespace interp 90353942Sdim} // namespace clang 91353942Sdim 92353942Sdimtemplate <class Emitter> 93353942Sdimbool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) { 94353942Sdim // Classify the return type. 95353942Sdim ReturnType = this->classify(F->getReturnType()); 96353942Sdim 97353942Sdim // Set up fields and context if a constructor. 98353942Sdim if (auto *MD = dyn_cast<CXXMethodDecl>(F)) 99353942Sdim return this->bail(MD); 100353942Sdim 101353942Sdim if (auto *Body = F->getBody()) 102353942Sdim if (!visitStmt(Body)) 103353942Sdim return false; 104353942Sdim 105353942Sdim // Emit a guard return to protect against a code path missing one. 106353942Sdim if (F->getReturnType()->isVoidType()) 107353942Sdim return this->emitRetVoid(SourceInfo{}); 108353942Sdim else 109353942Sdim return this->emitNoRet(SourceInfo{}); 110353942Sdim} 111353942Sdim 112353942Sdimtemplate <class Emitter> 113353942Sdimbool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) { 114353942Sdim switch (S->getStmtClass()) { 115353942Sdim case Stmt::CompoundStmtClass: 116353942Sdim return visitCompoundStmt(cast<CompoundStmt>(S)); 117353942Sdim case Stmt::DeclStmtClass: 118353942Sdim return visitDeclStmt(cast<DeclStmt>(S)); 119353942Sdim case Stmt::ReturnStmtClass: 120353942Sdim return visitReturnStmt(cast<ReturnStmt>(S)); 121353942Sdim case Stmt::IfStmtClass: 122353942Sdim return visitIfStmt(cast<IfStmt>(S)); 123353942Sdim case Stmt::NullStmtClass: 124353942Sdim return true; 125353942Sdim default: { 126353942Sdim if (auto *Exp = dyn_cast<Expr>(S)) 127353942Sdim return this->discard(Exp); 128353942Sdim return this->bail(S); 129353942Sdim } 130353942Sdim } 131353942Sdim} 132353942Sdim 133353942Sdimtemplate <class Emitter> 134353942Sdimbool ByteCodeStmtGen<Emitter>::visitCompoundStmt( 135353942Sdim const CompoundStmt *CompoundStmt) { 136353942Sdim BlockScope<Emitter> Scope(this); 137353942Sdim for (auto *InnerStmt : CompoundStmt->body()) 138353942Sdim if (!visitStmt(InnerStmt)) 139353942Sdim return false; 140353942Sdim return true; 141353942Sdim} 142353942Sdim 143353942Sdimtemplate <class Emitter> 144353942Sdimbool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) { 145353942Sdim for (auto *D : DS->decls()) { 146353942Sdim // Variable declarator. 147353942Sdim if (auto *VD = dyn_cast<VarDecl>(D)) { 148353942Sdim if (!visitVarDecl(VD)) 149353942Sdim return false; 150353942Sdim continue; 151353942Sdim } 152353942Sdim 153353942Sdim // Decomposition declarator. 154353942Sdim if (auto *DD = dyn_cast<DecompositionDecl>(D)) { 155353942Sdim return this->bail(DD); 156353942Sdim } 157353942Sdim } 158353942Sdim 159353942Sdim return true; 160353942Sdim} 161353942Sdim 162353942Sdimtemplate <class Emitter> 163353942Sdimbool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) { 164353942Sdim if (const Expr *RE = RS->getRetValue()) { 165353942Sdim ExprScope<Emitter> RetScope(this); 166353942Sdim if (ReturnType) { 167353942Sdim // Primitive types are simply returned. 168353942Sdim if (!this->visit(RE)) 169353942Sdim return false; 170353942Sdim this->emitCleanup(); 171353942Sdim return this->emitRet(*ReturnType, RS); 172353942Sdim } else { 173353942Sdim // RVO - construct the value in the return location. 174353942Sdim auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); }; 175353942Sdim if (!this->visitInitializer(RE, ReturnLocation)) 176353942Sdim return false; 177353942Sdim this->emitCleanup(); 178353942Sdim return this->emitRetVoid(RS); 179353942Sdim } 180353942Sdim } else { 181353942Sdim this->emitCleanup(); 182353942Sdim if (!this->emitRetVoid(RS)) 183353942Sdim return false; 184353942Sdim return true; 185353942Sdim } 186353942Sdim} 187353942Sdim 188353942Sdimtemplate <class Emitter> 189353942Sdimbool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) { 190353942Sdim BlockScope<Emitter> IfScope(this); 191353942Sdim if (auto *CondInit = IS->getInit()) 192353942Sdim if (!visitStmt(IS->getInit())) 193353942Sdim return false; 194353942Sdim 195353942Sdim if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt()) 196353942Sdim if (!visitDeclStmt(CondDecl)) 197353942Sdim return false; 198353942Sdim 199353942Sdim if (!this->visitBool(IS->getCond())) 200353942Sdim return false; 201353942Sdim 202353942Sdim if (const Stmt *Else = IS->getElse()) { 203353942Sdim LabelTy LabelElse = this->getLabel(); 204353942Sdim LabelTy LabelEnd = this->getLabel(); 205353942Sdim if (!this->jumpFalse(LabelElse)) 206353942Sdim return false; 207353942Sdim if (!visitStmt(IS->getThen())) 208353942Sdim return false; 209353942Sdim if (!this->jump(LabelEnd)) 210353942Sdim return false; 211353942Sdim this->emitLabel(LabelElse); 212353942Sdim if (!visitStmt(Else)) 213353942Sdim return false; 214353942Sdim this->emitLabel(LabelEnd); 215353942Sdim } else { 216353942Sdim LabelTy LabelEnd = this->getLabel(); 217353942Sdim if (!this->jumpFalse(LabelEnd)) 218353942Sdim return false; 219353942Sdim if (!visitStmt(IS->getThen())) 220353942Sdim return false; 221353942Sdim this->emitLabel(LabelEnd); 222353942Sdim } 223353942Sdim 224353942Sdim return true; 225353942Sdim} 226353942Sdim 227353942Sdimtemplate <class Emitter> 228353942Sdimbool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) { 229353942Sdim auto DT = VD->getType(); 230353942Sdim 231353942Sdim if (!VD->hasLocalStorage()) { 232353942Sdim // No code generation required. 233353942Sdim return true; 234353942Sdim } 235353942Sdim 236353942Sdim // Integers, pointers, primitives. 237353942Sdim if (Optional<PrimType> T = this->classify(DT)) { 238353942Sdim auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified()); 239353942Sdim // Compile the initialiser in its own scope. 240353942Sdim { 241353942Sdim ExprScope<Emitter> Scope(this); 242353942Sdim if (!this->visit(VD->getInit())) 243353942Sdim return false; 244353942Sdim } 245353942Sdim // Set the value. 246353942Sdim return this->emitSetLocal(*T, Off, VD); 247353942Sdim } else { 248353942Sdim // Composite types - allocate storage and initialize it. 249353942Sdim if (auto Off = this->allocateLocal(VD)) { 250353942Sdim return this->visitLocalInitializer(VD->getInit(), *Off); 251353942Sdim } else { 252353942Sdim return this->bail(VD); 253353942Sdim } 254353942Sdim } 255353942Sdim} 256353942Sdim 257353942Sdimnamespace clang { 258353942Sdimnamespace interp { 259353942Sdim 260353942Sdimtemplate class ByteCodeStmtGen<ByteCodeEmitter>; 261353942Sdim 262353942Sdim} // namespace interp 263353942Sdim} // namespace clang 264