Home | History | Annotate | Line # | Download | only in Interp
      1  1.1  joerg //===--- InterpFrame.cpp - Call Frame implementation for the VM -*- 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 "InterpFrame.h"
     10  1.1  joerg #include "Function.h"
     11  1.1  joerg #include "Interp.h"
     12  1.1  joerg #include "InterpStack.h"
     13  1.1  joerg #include "PrimType.h"
     14  1.1  joerg #include "Program.h"
     15  1.1  joerg #include "clang/AST/DeclCXX.h"
     16  1.1  joerg 
     17  1.1  joerg using namespace clang;
     18  1.1  joerg using namespace clang::interp;
     19  1.1  joerg 
     20  1.1  joerg InterpFrame::InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller,
     21  1.1  joerg                          CodePtr RetPC, Pointer &&This)
     22  1.1  joerg     : Caller(Caller), S(S), Func(Func), This(std::move(This)), RetPC(RetPC),
     23  1.1  joerg       ArgSize(Func ? Func->getArgSize() : 0),
     24  1.1  joerg       Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
     25  1.1  joerg   if (Func) {
     26  1.1  joerg     if (unsigned FrameSize = Func->getFrameSize()) {
     27  1.1  joerg       Locals = std::make_unique<char[]>(FrameSize);
     28  1.1  joerg       for (auto &Scope : Func->scopes()) {
     29  1.1  joerg         for (auto &Local : Scope.locals()) {
     30  1.1  joerg           Block *B = new (localBlock(Local.Offset)) Block(Local.Desc);
     31  1.1  joerg           B->invokeCtor();
     32  1.1  joerg         }
     33  1.1  joerg       }
     34  1.1  joerg     }
     35  1.1  joerg   }
     36  1.1  joerg }
     37  1.1  joerg 
     38  1.1  joerg InterpFrame::~InterpFrame() {
     39  1.1  joerg   if (Func && Func->isConstructor() && This.isBaseClass())
     40  1.1  joerg     This.initialize();
     41  1.1  joerg   for (auto &Param : Params)
     42  1.1  joerg     S.deallocate(reinterpret_cast<Block *>(Param.second.get()));
     43  1.1  joerg }
     44  1.1  joerg 
     45  1.1  joerg void InterpFrame::destroy(unsigned Idx) {
     46  1.1  joerg   for (auto &Local : Func->getScope(Idx).locals()) {
     47  1.1  joerg     S.deallocate(reinterpret_cast<Block *>(localBlock(Local.Offset)));
     48  1.1  joerg   }
     49  1.1  joerg }
     50  1.1  joerg 
     51  1.1  joerg void InterpFrame::popArgs() {
     52  1.1  joerg   for (PrimType Ty : Func->args_reverse())
     53  1.1  joerg     TYPE_SWITCH(Ty, S.Stk.discard<T>());
     54  1.1  joerg }
     55  1.1  joerg 
     56  1.1  joerg template <typename T>
     57  1.1  joerg static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType) {
     58  1.1  joerg   OS << V;
     59  1.1  joerg }
     60  1.1  joerg 
     61  1.1  joerg template <>
     62  1.1  joerg void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx,
     63  1.1  joerg            QualType Ty) {
     64  1.1  joerg   if (P.isZero()) {
     65  1.1  joerg     OS << "nullptr";
     66  1.1  joerg     return;
     67  1.1  joerg   }
     68  1.1  joerg 
     69  1.1  joerg   auto printDesc = [&OS, &Ctx](Descriptor *Desc) {
     70  1.1  joerg     if (auto *D = Desc->asDecl()) {
     71  1.1  joerg       // Subfields or named values.
     72  1.1  joerg       if (auto *VD = dyn_cast<ValueDecl>(D)) {
     73  1.1  joerg         OS << *VD;
     74  1.1  joerg         return;
     75  1.1  joerg       }
     76  1.1  joerg       // Base classes.
     77  1.1  joerg       if (isa<RecordDecl>(D)) {
     78  1.1  joerg         return;
     79  1.1  joerg       }
     80  1.1  joerg     }
     81  1.1  joerg     // Temporary expression.
     82  1.1  joerg     if (auto *E = Desc->asExpr()) {
     83  1.1  joerg       E->printPretty(OS, nullptr, Ctx.getPrintingPolicy());
     84  1.1  joerg       return;
     85  1.1  joerg     }
     86  1.1  joerg     llvm_unreachable("Invalid descriptor type");
     87  1.1  joerg   };
     88  1.1  joerg 
     89  1.1  joerg   if (!Ty->isReferenceType())
     90  1.1  joerg     OS << "&";
     91  1.1  joerg   llvm::SmallVector<Pointer, 2> Levels;
     92  1.1  joerg   for (Pointer F = P; !F.isRoot(); ) {
     93  1.1  joerg     Levels.push_back(F);
     94  1.1  joerg     F = F.isArrayElement() ? F.getArray().expand() : F.getBase();
     95  1.1  joerg   }
     96  1.1  joerg 
     97  1.1  joerg   printDesc(P.getDeclDesc());
     98  1.1  joerg   for (auto It = Levels.rbegin(); It != Levels.rend(); ++It) {
     99  1.1  joerg     if (It->inArray()) {
    100  1.1  joerg       OS << "[" << It->expand().getIndex() << "]";
    101  1.1  joerg       continue;
    102  1.1  joerg     }
    103  1.1  joerg     if (auto Index = It->getIndex()) {
    104  1.1  joerg       OS << " + " << Index;
    105  1.1  joerg       continue;
    106  1.1  joerg     }
    107  1.1  joerg     OS << ".";
    108  1.1  joerg     printDesc(It->getFieldDesc());
    109  1.1  joerg   }
    110  1.1  joerg }
    111  1.1  joerg 
    112  1.1  joerg void InterpFrame::describe(llvm::raw_ostream &OS) {
    113  1.1  joerg   const FunctionDecl *F = getCallee();
    114  1.1  joerg   auto *M = dyn_cast<CXXMethodDecl>(F);
    115  1.1  joerg   if (M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
    116  1.1  joerg     print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
    117  1.1  joerg     OS << "->";
    118  1.1  joerg   }
    119  1.1  joerg   OS << *F << "(";
    120  1.1  joerg   unsigned Off = Func->hasRVO() ? primSize(PT_Ptr) : 0;
    121  1.1  joerg   for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) {
    122  1.1  joerg     QualType Ty = F->getParamDecl(I)->getType();
    123  1.1  joerg 
    124  1.1  joerg     PrimType PrimTy;
    125  1.1  joerg     if (llvm::Optional<PrimType> T = S.Ctx.classify(Ty)) {
    126  1.1  joerg       PrimTy = *T;
    127  1.1  joerg     } else {
    128  1.1  joerg       PrimTy = PT_Ptr;
    129  1.1  joerg     }
    130  1.1  joerg 
    131  1.1  joerg     TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty));
    132  1.1  joerg     Off += align(primSize(PrimTy));
    133  1.1  joerg     if (I + 1 != N)
    134  1.1  joerg       OS << ", ";
    135  1.1  joerg   }
    136  1.1  joerg   OS << ")";
    137  1.1  joerg }
    138  1.1  joerg 
    139  1.1  joerg Frame *InterpFrame::getCaller() const {
    140  1.1  joerg   if (Caller->Caller)
    141  1.1  joerg     return Caller;
    142  1.1  joerg   return S.getSplitFrame();
    143  1.1  joerg }
    144  1.1  joerg 
    145  1.1  joerg SourceLocation InterpFrame::getCallLocation() const {
    146  1.1  joerg   if (!Caller->Func)
    147  1.1  joerg     return S.getLocation(nullptr, {});
    148  1.1  joerg   return S.getLocation(Caller->Func, RetPC - sizeof(uintptr_t));
    149  1.1  joerg }
    150  1.1  joerg 
    151  1.1  joerg const FunctionDecl *InterpFrame::getCallee() const {
    152  1.1  joerg   return Func->getDecl();
    153  1.1  joerg }
    154  1.1  joerg 
    155  1.1  joerg Pointer InterpFrame::getLocalPointer(unsigned Offset) {
    156  1.1  joerg   assert(Offset < Func->getFrameSize() && "Invalid local offset.");
    157  1.1  joerg   return Pointer(
    158  1.1  joerg       reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block)));
    159  1.1  joerg }
    160  1.1  joerg 
    161  1.1  joerg Pointer InterpFrame::getParamPointer(unsigned Off) {
    162  1.1  joerg   // Return the block if it was created previously.
    163  1.1  joerg   auto Pt = Params.find(Off);
    164  1.1  joerg   if (Pt != Params.end()) {
    165  1.1  joerg     return Pointer(reinterpret_cast<Block *>(Pt->second.get()));
    166  1.1  joerg   }
    167  1.1  joerg 
    168  1.1  joerg   // Allocate memory to store the parameter and the block metadata.
    169  1.1  joerg   const auto &Desc = Func->getParamDescriptor(Off);
    170  1.1  joerg   size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize();
    171  1.1  joerg   auto Memory = std::make_unique<char[]>(BlockSize);
    172  1.1  joerg   auto *B = new (Memory.get()) Block(Desc.second);
    173  1.1  joerg 
    174  1.1  joerg   // Copy the initial value.
    175  1.1  joerg   TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off)));
    176  1.1  joerg 
    177  1.1  joerg   // Record the param.
    178  1.1  joerg   Params.insert({Off, std::move(Memory)});
    179  1.1  joerg   return Pointer(B);
    180  1.1  joerg }
    181  1.1  joerg 
    182  1.1  joerg SourceInfo InterpFrame::getSource(CodePtr PC) const {
    183  1.1  joerg   return S.getSource(Func, PC);
    184  1.1  joerg }
    185  1.1  joerg 
    186  1.1  joerg const Expr *InterpFrame::getExpr(CodePtr PC) const {
    187  1.1  joerg   return S.getExpr(Func, PC);
    188  1.1  joerg }
    189  1.1  joerg 
    190  1.1  joerg SourceLocation InterpFrame::getLocation(CodePtr PC) const {
    191  1.1  joerg   return S.getLocation(Func, PC);
    192  1.1  joerg }
    193  1.1  joerg 
    194