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