Home | History | Annotate | Line # | Download | only in Interp
      1      1.1  joerg //===--- ByteCodeExprGen.h - 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 // Defines the constexpr bytecode compiler.
     10      1.1  joerg //
     11      1.1  joerg //===----------------------------------------------------------------------===//
     12      1.1  joerg 
     13      1.1  joerg #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
     14      1.1  joerg #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
     15      1.1  joerg 
     16      1.1  joerg #include "ByteCodeEmitter.h"
     17      1.1  joerg #include "EvalEmitter.h"
     18      1.1  joerg #include "Pointer.h"
     19      1.1  joerg #include "PrimType.h"
     20      1.1  joerg #include "Record.h"
     21      1.1  joerg #include "clang/AST/Decl.h"
     22      1.1  joerg #include "clang/AST/Expr.h"
     23      1.1  joerg #include "clang/AST/StmtVisitor.h"
     24  1.1.1.2  joerg #include "clang/Basic/TargetInfo.h"
     25      1.1  joerg #include "llvm/ADT/Optional.h"
     26      1.1  joerg 
     27      1.1  joerg namespace clang {
     28      1.1  joerg class QualType;
     29      1.1  joerg 
     30      1.1  joerg namespace interp {
     31      1.1  joerg class Function;
     32      1.1  joerg class State;
     33      1.1  joerg 
     34      1.1  joerg template <class Emitter> class LocalScope;
     35      1.1  joerg template <class Emitter> class RecordScope;
     36      1.1  joerg template <class Emitter> class VariableScope;
     37      1.1  joerg template <class Emitter> class DeclScope;
     38      1.1  joerg template <class Emitter> class OptionScope;
     39      1.1  joerg 
     40      1.1  joerg /// Compilation context for expressions.
     41      1.1  joerg template <class Emitter>
     42      1.1  joerg class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
     43      1.1  joerg                         public Emitter {
     44      1.1  joerg protected:
     45      1.1  joerg   // Emitters for opcodes of various arities.
     46      1.1  joerg   using NullaryFn = bool (ByteCodeExprGen::*)(const SourceInfo &);
     47      1.1  joerg   using UnaryFn = bool (ByteCodeExprGen::*)(PrimType, const SourceInfo &);
     48      1.1  joerg   using BinaryFn = bool (ByteCodeExprGen::*)(PrimType, PrimType,
     49      1.1  joerg                                              const SourceInfo &);
     50      1.1  joerg 
     51      1.1  joerg   // Aliases for types defined in the emitter.
     52      1.1  joerg   using LabelTy = typename Emitter::LabelTy;
     53      1.1  joerg   using AddrTy = typename Emitter::AddrTy;
     54      1.1  joerg 
     55      1.1  joerg   // Reference to a function generating the pointer of an initialized object.s
     56      1.1  joerg   using InitFnRef = std::function<bool()>;
     57      1.1  joerg 
     58      1.1  joerg   /// Current compilation context.
     59      1.1  joerg   Context &Ctx;
     60      1.1  joerg   /// Program to link to.
     61      1.1  joerg   Program &P;
     62      1.1  joerg 
     63      1.1  joerg public:
     64      1.1  joerg   /// Initializes the compiler and the backend emitter.
     65      1.1  joerg   template <typename... Tys>
     66      1.1  joerg   ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
     67      1.1  joerg       : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
     68      1.1  joerg 
     69      1.1  joerg   // Expression visitors - result returned on stack.
     70      1.1  joerg   bool VisitCastExpr(const CastExpr *E);
     71      1.1  joerg   bool VisitIntegerLiteral(const IntegerLiteral *E);
     72      1.1  joerg   bool VisitParenExpr(const ParenExpr *E);
     73      1.1  joerg   bool VisitBinaryOperator(const BinaryOperator *E);
     74      1.1  joerg 
     75      1.1  joerg protected:
     76      1.1  joerg   bool visitExpr(const Expr *E) override;
     77      1.1  joerg   bool visitDecl(const VarDecl *VD) override;
     78      1.1  joerg 
     79      1.1  joerg protected:
     80      1.1  joerg   /// Emits scope cleanup instructions.
     81      1.1  joerg   void emitCleanup();
     82      1.1  joerg 
     83      1.1  joerg   /// Returns a record type from a record or pointer type.
     84      1.1  joerg   const RecordType *getRecordTy(QualType Ty);
     85      1.1  joerg 
     86      1.1  joerg   /// Returns a record from a record or pointer type.
     87      1.1  joerg   Record *getRecord(QualType Ty);
     88      1.1  joerg   Record *getRecord(const RecordDecl *RD);
     89      1.1  joerg 
     90      1.1  joerg   /// Returns the size int bits of an integer.
     91      1.1  joerg   unsigned getIntWidth(QualType Ty) {
     92      1.1  joerg     auto &ASTContext = Ctx.getASTContext();
     93      1.1  joerg     return ASTContext.getIntWidth(Ty);
     94      1.1  joerg   }
     95      1.1  joerg 
     96      1.1  joerg   /// Returns the value of CHAR_BIT.
     97      1.1  joerg   unsigned getCharBit() const {
     98      1.1  joerg     auto &ASTContext = Ctx.getASTContext();
     99      1.1  joerg     return ASTContext.getTargetInfo().getCharWidth();
    100      1.1  joerg   }
    101      1.1  joerg 
    102      1.1  joerg   /// Classifies a type.
    103      1.1  joerg   llvm::Optional<PrimType> classify(const Expr *E) const {
    104      1.1  joerg     return E->isGLValue() ? PT_Ptr : classify(E->getType());
    105      1.1  joerg   }
    106      1.1  joerg   llvm::Optional<PrimType> classify(QualType Ty) const {
    107      1.1  joerg     return Ctx.classify(Ty);
    108      1.1  joerg   }
    109      1.1  joerg 
    110      1.1  joerg   /// Checks if a pointer needs adjustment.
    111      1.1  joerg   bool needsAdjust(QualType Ty) const {
    112      1.1  joerg     return true;
    113      1.1  joerg   }
    114      1.1  joerg 
    115      1.1  joerg   /// Classifies a known primitive type
    116      1.1  joerg   PrimType classifyPrim(QualType Ty) const {
    117      1.1  joerg     if (auto T = classify(Ty)) {
    118      1.1  joerg       return *T;
    119      1.1  joerg     }
    120      1.1  joerg     llvm_unreachable("not a primitive type");
    121      1.1  joerg   }
    122      1.1  joerg 
    123      1.1  joerg   /// Evaluates an expression for side effects and discards the result.
    124      1.1  joerg   bool discard(const Expr *E);
    125      1.1  joerg   /// Evaluates an expression and places result on stack.
    126      1.1  joerg   bool visit(const Expr *E);
    127      1.1  joerg   /// Compiles an initializer for a local.
    128      1.1  joerg   bool visitInitializer(const Expr *E, InitFnRef GenPtr);
    129      1.1  joerg 
    130      1.1  joerg   /// Visits an expression and converts it to a boolean.
    131      1.1  joerg   bool visitBool(const Expr *E);
    132      1.1  joerg 
    133      1.1  joerg   /// Visits an initializer for a local.
    134      1.1  joerg   bool visitLocalInitializer(const Expr *Init, unsigned I) {
    135      1.1  joerg     return visitInitializer(Init, [this, I, Init] {
    136      1.1  joerg       return this->emitGetPtrLocal(I, Init);
    137      1.1  joerg     });
    138      1.1  joerg   }
    139      1.1  joerg 
    140      1.1  joerg   /// Visits an initializer for a global.
    141      1.1  joerg   bool visitGlobalInitializer(const Expr *Init, unsigned I) {
    142      1.1  joerg     return visitInitializer(Init, [this, I, Init] {
    143      1.1  joerg       return this->emitGetPtrGlobal(I, Init);
    144      1.1  joerg     });
    145      1.1  joerg   }
    146      1.1  joerg 
    147      1.1  joerg   /// Visits a delegated initializer.
    148      1.1  joerg   bool visitThisInitializer(const Expr *I) {
    149      1.1  joerg     return visitInitializer(I, [this, I] { return this->emitThis(I); });
    150      1.1  joerg   }
    151      1.1  joerg 
    152      1.1  joerg   /// Creates a local primitive value.
    153      1.1  joerg   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable,
    154      1.1  joerg                                   bool IsExtended = false);
    155      1.1  joerg 
    156      1.1  joerg   /// Allocates a space storing a local given its type.
    157      1.1  joerg   llvm::Optional<unsigned> allocateLocal(DeclTy &&Decl,
    158      1.1  joerg                                          bool IsExtended = false);
    159      1.1  joerg 
    160      1.1  joerg private:
    161      1.1  joerg   friend class VariableScope<Emitter>;
    162      1.1  joerg   friend class LocalScope<Emitter>;
    163      1.1  joerg   friend class RecordScope<Emitter>;
    164      1.1  joerg   friend class DeclScope<Emitter>;
    165      1.1  joerg   friend class OptionScope<Emitter>;
    166      1.1  joerg 
    167      1.1  joerg   /// Emits a zero initializer.
    168      1.1  joerg   bool visitZeroInitializer(PrimType T, const Expr *E);
    169      1.1  joerg 
    170      1.1  joerg   enum class DerefKind {
    171      1.1  joerg     /// Value is read and pushed to stack.
    172      1.1  joerg     Read,
    173      1.1  joerg     /// Direct method generates a value which is written. Returns pointer.
    174      1.1  joerg     Write,
    175      1.1  joerg     /// Direct method receives the value, pushes mutated value. Returns pointer.
    176      1.1  joerg     ReadWrite,
    177      1.1  joerg   };
    178      1.1  joerg 
    179      1.1  joerg   /// Method to directly load a value. If the value can be fetched directly,
    180      1.1  joerg   /// the direct handler is called. Otherwise, a pointer is left on the stack
    181      1.1  joerg   /// and the indirect handler is expected to operate on that.
    182      1.1  joerg   bool dereference(const Expr *LV, DerefKind AK,
    183      1.1  joerg                    llvm::function_ref<bool(PrimType)> Direct,
    184      1.1  joerg                    llvm::function_ref<bool(PrimType)> Indirect);
    185      1.1  joerg   bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD,
    186      1.1  joerg                         DerefKind AK,
    187      1.1  joerg                         llvm::function_ref<bool(PrimType)> Direct,
    188      1.1  joerg                         llvm::function_ref<bool(PrimType)> Indirect);
    189      1.1  joerg   bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD,
    190      1.1  joerg                       DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
    191      1.1  joerg                       llvm::function_ref<bool(PrimType)> Indirect);
    192      1.1  joerg 
    193      1.1  joerg   /// Emits an APInt constant.
    194      1.1  joerg   bool emitConst(PrimType T, unsigned NumBits, const llvm::APInt &Value,
    195      1.1  joerg                  const Expr *E);
    196      1.1  joerg 
    197      1.1  joerg   /// Emits an integer constant.
    198      1.1  joerg   template <typename T> bool emitConst(const Expr *E, T Value) {
    199      1.1  joerg     QualType Ty = E->getType();
    200      1.1  joerg     unsigned NumBits = getIntWidth(Ty);
    201      1.1  joerg     APInt WrappedValue(NumBits, Value, std::is_signed<T>::value);
    202      1.1  joerg     return emitConst(*Ctx.classify(Ty), NumBits, WrappedValue, E);
    203      1.1  joerg   }
    204      1.1  joerg 
    205      1.1  joerg   /// Returns a pointer to a variable declaration.
    206      1.1  joerg   bool getPtrVarDecl(const VarDecl *VD, const Expr *E);
    207      1.1  joerg 
    208      1.1  joerg   /// Returns the index of a global.
    209      1.1  joerg   llvm::Optional<unsigned> getGlobalIdx(const VarDecl *VD);
    210      1.1  joerg 
    211      1.1  joerg   /// Emits the initialized pointer.
    212      1.1  joerg   bool emitInitFn() {
    213      1.1  joerg     assert(InitFn && "missing initializer");
    214      1.1  joerg     return (*InitFn)();
    215      1.1  joerg   }
    216      1.1  joerg 
    217      1.1  joerg protected:
    218      1.1  joerg   /// Variable to storage mapping.
    219      1.1  joerg   llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
    220      1.1  joerg 
    221      1.1  joerg   /// OpaqueValueExpr to location mapping.
    222      1.1  joerg   llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
    223      1.1  joerg 
    224      1.1  joerg   /// Current scope.
    225      1.1  joerg   VariableScope<Emitter> *VarScope = nullptr;
    226      1.1  joerg 
    227      1.1  joerg   /// Current argument index.
    228      1.1  joerg   llvm::Optional<uint64_t> ArrayIndex;
    229      1.1  joerg 
    230      1.1  joerg   /// Flag indicating if return value is to be discarded.
    231      1.1  joerg   bool DiscardResult = false;
    232      1.1  joerg 
    233      1.1  joerg   /// Expression being initialized.
    234      1.1  joerg   llvm::Optional<InitFnRef> InitFn = {};
    235      1.1  joerg };
    236      1.1  joerg 
    237      1.1  joerg extern template class ByteCodeExprGen<ByteCodeEmitter>;
    238      1.1  joerg extern template class ByteCodeExprGen<EvalEmitter>;
    239      1.1  joerg 
    240      1.1  joerg /// Scope chain managing the variable lifetimes.
    241      1.1  joerg template <class Emitter> class VariableScope {
    242      1.1  joerg public:
    243      1.1  joerg   virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
    244      1.1  joerg 
    245      1.1  joerg   void add(const Scope::Local &Local, bool IsExtended) {
    246      1.1  joerg     if (IsExtended)
    247      1.1  joerg       this->addExtended(Local);
    248      1.1  joerg     else
    249      1.1  joerg       this->addLocal(Local);
    250      1.1  joerg   }
    251      1.1  joerg 
    252      1.1  joerg   virtual void addLocal(const Scope::Local &Local) {
    253      1.1  joerg     if (this->Parent)
    254      1.1  joerg       this->Parent->addLocal(Local);
    255      1.1  joerg   }
    256      1.1  joerg 
    257      1.1  joerg   virtual void addExtended(const Scope::Local &Local) {
    258      1.1  joerg     if (this->Parent)
    259      1.1  joerg       this->Parent->addExtended(Local);
    260      1.1  joerg   }
    261      1.1  joerg 
    262      1.1  joerg   virtual void emitDestruction() {}
    263      1.1  joerg 
    264      1.1  joerg   VariableScope *getParent() { return Parent; }
    265      1.1  joerg 
    266      1.1  joerg protected:
    267      1.1  joerg   VariableScope(ByteCodeExprGen<Emitter> *Ctx)
    268      1.1  joerg       : Ctx(Ctx), Parent(Ctx->VarScope) {
    269      1.1  joerg     Ctx->VarScope = this;
    270      1.1  joerg   }
    271      1.1  joerg 
    272      1.1  joerg   /// ByteCodeExprGen instance.
    273      1.1  joerg   ByteCodeExprGen<Emitter> *Ctx;
    274      1.1  joerg   /// Link to the parent scope.
    275      1.1  joerg   VariableScope *Parent;
    276      1.1  joerg };
    277      1.1  joerg 
    278      1.1  joerg /// Scope for local variables.
    279      1.1  joerg ///
    280      1.1  joerg /// When the scope is destroyed, instructions are emitted to tear down
    281      1.1  joerg /// all variables declared in this scope.
    282      1.1  joerg template <class Emitter> class LocalScope : public VariableScope<Emitter> {
    283      1.1  joerg public:
    284      1.1  joerg   LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
    285      1.1  joerg 
    286      1.1  joerg   ~LocalScope() override { this->emitDestruction(); }
    287      1.1  joerg 
    288      1.1  joerg   void addLocal(const Scope::Local &Local) override {
    289      1.1  joerg     if (!Idx.hasValue()) {
    290      1.1  joerg       Idx = this->Ctx->Descriptors.size();
    291      1.1  joerg       this->Ctx->Descriptors.emplace_back();
    292      1.1  joerg     }
    293      1.1  joerg 
    294      1.1  joerg     this->Ctx->Descriptors[*Idx].emplace_back(Local);
    295      1.1  joerg   }
    296      1.1  joerg 
    297      1.1  joerg   void emitDestruction() override {
    298      1.1  joerg     if (!Idx.hasValue())
    299      1.1  joerg       return;
    300      1.1  joerg     this->Ctx->emitDestroy(*Idx, SourceInfo{});
    301      1.1  joerg   }
    302      1.1  joerg 
    303      1.1  joerg protected:
    304      1.1  joerg   /// Index of the scope in the chain.
    305      1.1  joerg   Optional<unsigned> Idx;
    306      1.1  joerg };
    307      1.1  joerg 
    308      1.1  joerg /// Scope for storage declared in a compound statement.
    309      1.1  joerg template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
    310      1.1  joerg public:
    311      1.1  joerg   BlockScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
    312      1.1  joerg 
    313      1.1  joerg   void addExtended(const Scope::Local &Local) override {
    314      1.1  joerg     llvm_unreachable("Cannot create temporaries in full scopes");
    315      1.1  joerg   }
    316      1.1  joerg };
    317      1.1  joerg 
    318      1.1  joerg /// Expression scope which tracks potentially lifetime extended
    319      1.1  joerg /// temporaries which are hoisted to the parent scope on exit.
    320      1.1  joerg template <class Emitter> class ExprScope final : public LocalScope<Emitter> {
    321      1.1  joerg public:
    322      1.1  joerg   ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
    323      1.1  joerg 
    324      1.1  joerg   void addExtended(const Scope::Local &Local) override {
    325      1.1  joerg     this->Parent->addLocal(Local);
    326      1.1  joerg   }
    327      1.1  joerg };
    328      1.1  joerg 
    329      1.1  joerg } // namespace interp
    330      1.1  joerg } // namespace clang
    331      1.1  joerg 
    332      1.1  joerg #endif
    333