1353942Sdim//===--- InterpFrame.cpp - Call Frame implementation for the VM -*- 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 "InterpFrame.h" 10353942Sdim#include "Function.h" 11353942Sdim#include "Interp.h" 12353942Sdim#include "InterpStack.h" 13353942Sdim#include "PrimType.h" 14353942Sdim#include "Program.h" 15353942Sdim#include "clang/AST/DeclCXX.h" 16353942Sdim 17353942Sdimusing namespace clang; 18353942Sdimusing namespace clang::interp; 19353942Sdim 20353942SdimInterpFrame::InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller, 21353942Sdim CodePtr RetPC, Pointer &&This) 22353942Sdim : Caller(Caller), S(S), Func(Func), This(std::move(This)), RetPC(RetPC), 23353942Sdim ArgSize(Func ? Func->getArgSize() : 0), 24353942Sdim Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) { 25353942Sdim if (Func) { 26353942Sdim if (unsigned FrameSize = Func->getFrameSize()) { 27353942Sdim Locals = std::make_unique<char[]>(FrameSize); 28353942Sdim for (auto &Scope : Func->scopes()) { 29353942Sdim for (auto &Local : Scope.locals()) { 30353942Sdim Block *B = new (localBlock(Local.Offset)) Block(Local.Desc); 31353942Sdim B->invokeCtor(); 32353942Sdim } 33353942Sdim } 34353942Sdim } 35353942Sdim } 36353942Sdim} 37353942Sdim 38353942SdimInterpFrame::~InterpFrame() { 39353942Sdim if (Func && Func->isConstructor() && This.isBaseClass()) 40353942Sdim This.initialize(); 41353942Sdim for (auto &Param : Params) 42353942Sdim S.deallocate(reinterpret_cast<Block *>(Param.second.get())); 43353942Sdim} 44353942Sdim 45353942Sdimvoid InterpFrame::destroy(unsigned Idx) { 46353942Sdim for (auto &Local : Func->getScope(Idx).locals()) { 47353942Sdim S.deallocate(reinterpret_cast<Block *>(localBlock(Local.Offset))); 48353942Sdim } 49353942Sdim} 50353942Sdim 51353942Sdimvoid InterpFrame::popArgs() { 52353942Sdim for (PrimType Ty : Func->args_reverse()) 53353942Sdim TYPE_SWITCH(Ty, S.Stk.discard<T>()); 54353942Sdim} 55353942Sdim 56353942Sdimtemplate <typename T> 57353942Sdimstatic void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType) { 58353942Sdim OS << V; 59353942Sdim} 60353942Sdim 61353942Sdimtemplate <> 62353942Sdimvoid print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, 63353942Sdim QualType Ty) { 64353942Sdim if (P.isZero()) { 65353942Sdim OS << "nullptr"; 66353942Sdim return; 67353942Sdim } 68353942Sdim 69353942Sdim auto printDesc = [&OS, &Ctx](Descriptor *Desc) { 70353942Sdim if (auto *D = Desc->asDecl()) { 71353942Sdim // Subfields or named values. 72353942Sdim if (auto *VD = dyn_cast<ValueDecl>(D)) { 73353942Sdim OS << *VD; 74353942Sdim return; 75353942Sdim } 76353942Sdim // Base classes. 77353942Sdim if (isa<RecordDecl>(D)) { 78353942Sdim return; 79353942Sdim } 80353942Sdim } 81353942Sdim // Temporary expression. 82353942Sdim if (auto *E = Desc->asExpr()) { 83353942Sdim E->printPretty(OS, nullptr, Ctx.getPrintingPolicy()); 84353942Sdim return; 85353942Sdim } 86353942Sdim llvm_unreachable("Invalid descriptor type"); 87353942Sdim }; 88353942Sdim 89353942Sdim if (!Ty->isReferenceType()) 90353942Sdim OS << "&"; 91353942Sdim llvm::SmallVector<Pointer, 2> Levels; 92353942Sdim for (Pointer F = P; !F.isRoot(); ) { 93353942Sdim Levels.push_back(F); 94353942Sdim F = F.isArrayElement() ? F.getArray().expand() : F.getBase(); 95353942Sdim } 96353942Sdim 97353942Sdim printDesc(P.getDeclDesc()); 98353942Sdim for (auto It = Levels.rbegin(); It != Levels.rend(); ++It) { 99353942Sdim if (It->inArray()) { 100353942Sdim OS << "[" << It->expand().getIndex() << "]"; 101353942Sdim continue; 102353942Sdim } 103353942Sdim if (auto Index = It->getIndex()) { 104353942Sdim OS << " + " << Index; 105353942Sdim continue; 106353942Sdim } 107353942Sdim OS << "."; 108353942Sdim printDesc(It->getFieldDesc()); 109353942Sdim } 110353942Sdim} 111353942Sdim 112353942Sdimvoid InterpFrame::describe(llvm::raw_ostream &OS) { 113353942Sdim const FunctionDecl *F = getCallee(); 114353942Sdim auto *M = dyn_cast<CXXMethodDecl>(F); 115353942Sdim if (M && M->isInstance() && !isa<CXXConstructorDecl>(F)) { 116353942Sdim print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent())); 117353942Sdim OS << "->"; 118353942Sdim } 119353942Sdim OS << *F << "("; 120353942Sdim unsigned Off = Func->hasRVO() ? primSize(PT_Ptr) : 0; 121353942Sdim for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) { 122353942Sdim QualType Ty = F->getParamDecl(I)->getType(); 123353942Sdim 124353942Sdim PrimType PrimTy; 125353942Sdim if (llvm::Optional<PrimType> T = S.Ctx.classify(Ty)) { 126353942Sdim PrimTy = *T; 127353942Sdim } else { 128353942Sdim PrimTy = PT_Ptr; 129353942Sdim } 130353942Sdim 131353942Sdim TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty)); 132353942Sdim Off += align(primSize(PrimTy)); 133353942Sdim if (I + 1 != N) 134353942Sdim OS << ", "; 135353942Sdim } 136353942Sdim OS << ")"; 137353942Sdim} 138353942Sdim 139353942SdimFrame *InterpFrame::getCaller() const { 140353942Sdim if (Caller->Caller) 141353942Sdim return Caller; 142353942Sdim return S.getSplitFrame(); 143353942Sdim} 144353942Sdim 145353942SdimSourceLocation InterpFrame::getCallLocation() const { 146353942Sdim if (!Caller->Func) 147353942Sdim return S.getLocation(nullptr, {}); 148353942Sdim return S.getLocation(Caller->Func, RetPC - sizeof(uintptr_t)); 149353942Sdim} 150353942Sdim 151353942Sdimconst FunctionDecl *InterpFrame::getCallee() const { 152353942Sdim return Func->getDecl(); 153353942Sdim} 154353942Sdim 155353942SdimPointer InterpFrame::getLocalPointer(unsigned Offset) { 156353942Sdim assert(Offset < Func->getFrameSize() && "Invalid local offset."); 157353942Sdim return Pointer( 158353942Sdim reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block))); 159353942Sdim} 160353942Sdim 161353942SdimPointer InterpFrame::getParamPointer(unsigned Off) { 162353942Sdim // Return the block if it was created previously. 163353942Sdim auto Pt = Params.find(Off); 164353942Sdim if (Pt != Params.end()) { 165353942Sdim return Pointer(reinterpret_cast<Block *>(Pt->second.get())); 166353942Sdim } 167353942Sdim 168353942Sdim // Allocate memory to store the parameter and the block metadata. 169353942Sdim const auto &Desc = Func->getParamDescriptor(Off); 170353942Sdim size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize(); 171353942Sdim auto Memory = std::make_unique<char[]>(BlockSize); 172353942Sdim auto *B = new (Memory.get()) Block(Desc.second); 173353942Sdim 174353942Sdim // Copy the initial value. 175353942Sdim TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off))); 176353942Sdim 177353942Sdim // Record the param. 178353942Sdim Params.insert({Off, std::move(Memory)}); 179353942Sdim return Pointer(B); 180353942Sdim} 181353942Sdim 182353942SdimSourceInfo InterpFrame::getSource(CodePtr PC) const { 183353942Sdim return S.getSource(Func, PC); 184353942Sdim} 185353942Sdim 186353942Sdimconst Expr *InterpFrame::getExpr(CodePtr PC) const { 187353942Sdim return S.getExpr(Func, PC); 188353942Sdim} 189353942Sdim 190353942SdimSourceLocation InterpFrame::getLocation(CodePtr PC) const { 191353942Sdim return S.getLocation(Func, PC); 192353942Sdim} 193353942Sdim 194