Home | History | Annotate | Line # | Download | only in Interp
      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