1*a07aba5dSTimm Baeder //===--- InterpFrame.cpp - Call Frame implementation for the VM -*- C++ -*-===// 2*a07aba5dSTimm Baeder // 3*a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5*a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a07aba5dSTimm Baeder // 7*a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8*a07aba5dSTimm Baeder 9*a07aba5dSTimm Baeder #include "InterpFrame.h" 10*a07aba5dSTimm Baeder #include "Boolean.h" 11*a07aba5dSTimm Baeder #include "Floating.h" 12*a07aba5dSTimm Baeder #include "Function.h" 13*a07aba5dSTimm Baeder #include "InterpStack.h" 14*a07aba5dSTimm Baeder #include "InterpState.h" 15*a07aba5dSTimm Baeder #include "MemberPointer.h" 16*a07aba5dSTimm Baeder #include "Pointer.h" 17*a07aba5dSTimm Baeder #include "PrimType.h" 18*a07aba5dSTimm Baeder #include "Program.h" 19*a07aba5dSTimm Baeder #include "clang/AST/ASTContext.h" 20*a07aba5dSTimm Baeder #include "clang/AST/DeclCXX.h" 21*a07aba5dSTimm Baeder #include "clang/AST/ExprCXX.h" 22*a07aba5dSTimm Baeder 23*a07aba5dSTimm Baeder using namespace clang; 24*a07aba5dSTimm Baeder using namespace clang::interp; 25*a07aba5dSTimm Baeder 26*a07aba5dSTimm Baeder InterpFrame::InterpFrame(InterpState &S, const Function *Func, 27*a07aba5dSTimm Baeder InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize) 28*a07aba5dSTimm Baeder : Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func), 29*a07aba5dSTimm Baeder RetPC(RetPC), ArgSize(ArgSize), Args(static_cast<char *>(S.Stk.top())), 30*a07aba5dSTimm Baeder FrameOffset(S.Stk.size()) { 31*a07aba5dSTimm Baeder if (!Func) 32*a07aba5dSTimm Baeder return; 33*a07aba5dSTimm Baeder 34*a07aba5dSTimm Baeder unsigned FrameSize = Func->getFrameSize(); 35*a07aba5dSTimm Baeder if (FrameSize == 0) 36*a07aba5dSTimm Baeder return; 37*a07aba5dSTimm Baeder 38*a07aba5dSTimm Baeder Locals = std::make_unique<char[]>(FrameSize); 39*a07aba5dSTimm Baeder for (auto &Scope : Func->scopes()) { 40*a07aba5dSTimm Baeder for (auto &Local : Scope.locals()) { 41*a07aba5dSTimm Baeder new (localBlock(Local.Offset)) Block(S.Ctx.getEvalID(), Local.Desc); 42*a07aba5dSTimm Baeder // Note that we are NOT calling invokeCtor() here, since that is done 43*a07aba5dSTimm Baeder // via the InitScope op. 44*a07aba5dSTimm Baeder new (localInlineDesc(Local.Offset)) InlineDescriptor(Local.Desc); 45*a07aba5dSTimm Baeder } 46*a07aba5dSTimm Baeder } 47*a07aba5dSTimm Baeder } 48*a07aba5dSTimm Baeder 49*a07aba5dSTimm Baeder InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC, 50*a07aba5dSTimm Baeder unsigned VarArgSize) 51*a07aba5dSTimm Baeder : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) { 52*a07aba5dSTimm Baeder // As per our calling convention, the this pointer is 53*a07aba5dSTimm Baeder // part of the ArgSize. 54*a07aba5dSTimm Baeder // If the function has RVO, the RVO pointer is first. 55*a07aba5dSTimm Baeder // If the fuction has a This pointer, that one is next. 56*a07aba5dSTimm Baeder // Then follow the actual arguments (but those are handled 57*a07aba5dSTimm Baeder // in getParamPointer()). 58*a07aba5dSTimm Baeder if (Func->hasRVO()) 59*a07aba5dSTimm Baeder RVOPtr = stackRef<Pointer>(0); 60*a07aba5dSTimm Baeder 61*a07aba5dSTimm Baeder if (Func->hasThisPointer()) { 62*a07aba5dSTimm Baeder if (Func->hasRVO()) 63*a07aba5dSTimm Baeder This = stackRef<Pointer>(sizeof(Pointer)); 64*a07aba5dSTimm Baeder else 65*a07aba5dSTimm Baeder This = stackRef<Pointer>(0); 66*a07aba5dSTimm Baeder } 67*a07aba5dSTimm Baeder } 68*a07aba5dSTimm Baeder 69*a07aba5dSTimm Baeder InterpFrame::~InterpFrame() { 70*a07aba5dSTimm Baeder for (auto &Param : Params) 71*a07aba5dSTimm Baeder S.deallocate(reinterpret_cast<Block *>(Param.second.get())); 72*a07aba5dSTimm Baeder 73*a07aba5dSTimm Baeder // When destroying the InterpFrame, call the Dtor for all block 74*a07aba5dSTimm Baeder // that haven't been destroyed via a destroy() op yet. 75*a07aba5dSTimm Baeder // This happens when the execution is interruped midway-through. 76*a07aba5dSTimm Baeder if (Func) { 77*a07aba5dSTimm Baeder for (auto &Scope : Func->scopes()) { 78*a07aba5dSTimm Baeder for (auto &Local : Scope.locals()) { 79*a07aba5dSTimm Baeder S.deallocate(localBlock(Local.Offset)); 80*a07aba5dSTimm Baeder } 81*a07aba5dSTimm Baeder } 82*a07aba5dSTimm Baeder } 83*a07aba5dSTimm Baeder } 84*a07aba5dSTimm Baeder 85*a07aba5dSTimm Baeder void InterpFrame::initScope(unsigned Idx) { 86*a07aba5dSTimm Baeder if (!Func) 87*a07aba5dSTimm Baeder return; 88*a07aba5dSTimm Baeder for (auto &Local : Func->getScope(Idx).locals()) { 89*a07aba5dSTimm Baeder localBlock(Local.Offset)->invokeCtor(); 90*a07aba5dSTimm Baeder } 91*a07aba5dSTimm Baeder } 92*a07aba5dSTimm Baeder 93*a07aba5dSTimm Baeder void InterpFrame::destroy(unsigned Idx) { 94*a07aba5dSTimm Baeder for (auto &Local : Func->getScope(Idx).locals()) { 95*a07aba5dSTimm Baeder S.deallocate(localBlock(Local.Offset)); 96*a07aba5dSTimm Baeder } 97*a07aba5dSTimm Baeder } 98*a07aba5dSTimm Baeder 99*a07aba5dSTimm Baeder void InterpFrame::popArgs() { 100*a07aba5dSTimm Baeder for (PrimType Ty : Func->args_reverse()) 101*a07aba5dSTimm Baeder TYPE_SWITCH(Ty, S.Stk.discard<T>()); 102*a07aba5dSTimm Baeder } 103*a07aba5dSTimm Baeder 104*a07aba5dSTimm Baeder template <typename T> 105*a07aba5dSTimm Baeder static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, 106*a07aba5dSTimm Baeder QualType Ty) { 107*a07aba5dSTimm Baeder V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty); 108*a07aba5dSTimm Baeder } 109*a07aba5dSTimm Baeder 110*a07aba5dSTimm Baeder template <> 111*a07aba5dSTimm Baeder void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, 112*a07aba5dSTimm Baeder QualType Ty) { 113*a07aba5dSTimm Baeder if (P.isZero()) { 114*a07aba5dSTimm Baeder OS << "nullptr"; 115*a07aba5dSTimm Baeder return; 116*a07aba5dSTimm Baeder } 117*a07aba5dSTimm Baeder 118*a07aba5dSTimm Baeder auto printDesc = [&OS, &Ctx](const Descriptor *Desc) { 119*a07aba5dSTimm Baeder if (const auto *D = Desc->asDecl()) { 120*a07aba5dSTimm Baeder // Subfields or named values. 121*a07aba5dSTimm Baeder if (const auto *VD = dyn_cast<ValueDecl>(D)) { 122*a07aba5dSTimm Baeder OS << *VD; 123*a07aba5dSTimm Baeder return; 124*a07aba5dSTimm Baeder } 125*a07aba5dSTimm Baeder // Base classes. 126*a07aba5dSTimm Baeder if (isa<RecordDecl>(D)) 127*a07aba5dSTimm Baeder return; 128*a07aba5dSTimm Baeder } 129*a07aba5dSTimm Baeder // Temporary expression. 130*a07aba5dSTimm Baeder if (const auto *E = Desc->asExpr()) { 131*a07aba5dSTimm Baeder E->printPretty(OS, nullptr, Ctx.getPrintingPolicy()); 132*a07aba5dSTimm Baeder return; 133*a07aba5dSTimm Baeder } 134*a07aba5dSTimm Baeder llvm_unreachable("Invalid descriptor type"); 135*a07aba5dSTimm Baeder }; 136*a07aba5dSTimm Baeder 137*a07aba5dSTimm Baeder if (!Ty->isReferenceType()) 138*a07aba5dSTimm Baeder OS << "&"; 139*a07aba5dSTimm Baeder llvm::SmallVector<Pointer, 2> Levels; 140*a07aba5dSTimm Baeder for (Pointer F = P; !F.isRoot();) { 141*a07aba5dSTimm Baeder Levels.push_back(F); 142*a07aba5dSTimm Baeder F = F.isArrayElement() ? F.getArray().expand() : F.getBase(); 143*a07aba5dSTimm Baeder } 144*a07aba5dSTimm Baeder 145*a07aba5dSTimm Baeder // Drop the first pointer since we print it unconditionally anyway. 146*a07aba5dSTimm Baeder if (!Levels.empty()) 147*a07aba5dSTimm Baeder Levels.erase(Levels.begin()); 148*a07aba5dSTimm Baeder 149*a07aba5dSTimm Baeder printDesc(P.getDeclDesc()); 150*a07aba5dSTimm Baeder for (const auto &It : Levels) { 151*a07aba5dSTimm Baeder if (It.inArray()) { 152*a07aba5dSTimm Baeder OS << "[" << It.expand().getIndex() << "]"; 153*a07aba5dSTimm Baeder continue; 154*a07aba5dSTimm Baeder } 155*a07aba5dSTimm Baeder if (auto Index = It.getIndex()) { 156*a07aba5dSTimm Baeder OS << " + " << Index; 157*a07aba5dSTimm Baeder continue; 158*a07aba5dSTimm Baeder } 159*a07aba5dSTimm Baeder OS << "."; 160*a07aba5dSTimm Baeder printDesc(It.getFieldDesc()); 161*a07aba5dSTimm Baeder } 162*a07aba5dSTimm Baeder } 163*a07aba5dSTimm Baeder 164*a07aba5dSTimm Baeder void InterpFrame::describe(llvm::raw_ostream &OS) const { 165*a07aba5dSTimm Baeder // We create frames for builtin functions as well, but we can't reliably 166*a07aba5dSTimm Baeder // diagnose them. The 'in call to' diagnostics for them add no value to the 167*a07aba5dSTimm Baeder // user _and_ it doesn't generally work since the argument types don't always 168*a07aba5dSTimm Baeder // match the function prototype. Just ignore them. 169*a07aba5dSTimm Baeder // Similarly, for lambda static invokers, we would just print __invoke(). 170*a07aba5dSTimm Baeder if (const auto *F = getFunction(); 171*a07aba5dSTimm Baeder F && (F->isBuiltin() || F->isLambdaStaticInvoker())) 172*a07aba5dSTimm Baeder return; 173*a07aba5dSTimm Baeder 174*a07aba5dSTimm Baeder const Expr *CallExpr = Caller->getExpr(getRetPC()); 175*a07aba5dSTimm Baeder const FunctionDecl *F = getCallee(); 176*a07aba5dSTimm Baeder bool IsMemberCall = isa<CXXMethodDecl>(F) && !isa<CXXConstructorDecl>(F) && 177*a07aba5dSTimm Baeder cast<CXXMethodDecl>(F)->isImplicitObjectMemberFunction(); 178*a07aba5dSTimm Baeder if (Func->hasThisPointer() && IsMemberCall) { 179*a07aba5dSTimm Baeder if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) { 180*a07aba5dSTimm Baeder const Expr *Object = MCE->getImplicitObjectArgument(); 181*a07aba5dSTimm Baeder Object->printPretty(OS, /*Helper=*/nullptr, 182*a07aba5dSTimm Baeder S.getCtx().getPrintingPolicy(), 183*a07aba5dSTimm Baeder /*Indentation=*/0); 184*a07aba5dSTimm Baeder if (Object->getType()->isPointerType()) 185*a07aba5dSTimm Baeder OS << "->"; 186*a07aba5dSTimm Baeder else 187*a07aba5dSTimm Baeder OS << "."; 188*a07aba5dSTimm Baeder } else if (const auto *OCE = 189*a07aba5dSTimm Baeder dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) { 190*a07aba5dSTimm Baeder OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr, 191*a07aba5dSTimm Baeder S.getCtx().getPrintingPolicy(), 192*a07aba5dSTimm Baeder /*Indentation=*/0); 193*a07aba5dSTimm Baeder OS << "."; 194*a07aba5dSTimm Baeder } else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) { 195*a07aba5dSTimm Baeder print(OS, This, S.getCtx(), 196*a07aba5dSTimm Baeder S.getCtx().getLValueReferenceType( 197*a07aba5dSTimm Baeder S.getCtx().getRecordType(M->getParent()))); 198*a07aba5dSTimm Baeder OS << "."; 199*a07aba5dSTimm Baeder } 200*a07aba5dSTimm Baeder } 201*a07aba5dSTimm Baeder 202*a07aba5dSTimm Baeder F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(), 203*a07aba5dSTimm Baeder /*Qualified=*/false); 204*a07aba5dSTimm Baeder OS << '('; 205*a07aba5dSTimm Baeder unsigned Off = 0; 206*a07aba5dSTimm Baeder 207*a07aba5dSTimm Baeder Off += Func->hasRVO() ? primSize(PT_Ptr) : 0; 208*a07aba5dSTimm Baeder Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0; 209*a07aba5dSTimm Baeder 210*a07aba5dSTimm Baeder for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) { 211*a07aba5dSTimm Baeder QualType Ty = F->getParamDecl(I)->getType(); 212*a07aba5dSTimm Baeder 213*a07aba5dSTimm Baeder PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr); 214*a07aba5dSTimm Baeder 215*a07aba5dSTimm Baeder TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty)); 216*a07aba5dSTimm Baeder Off += align(primSize(PrimTy)); 217*a07aba5dSTimm Baeder if (I + 1 != N) 218*a07aba5dSTimm Baeder OS << ", "; 219*a07aba5dSTimm Baeder } 220*a07aba5dSTimm Baeder OS << ")"; 221*a07aba5dSTimm Baeder } 222*a07aba5dSTimm Baeder 223*a07aba5dSTimm Baeder Frame *InterpFrame::getCaller() const { 224*a07aba5dSTimm Baeder if (Caller->Caller) 225*a07aba5dSTimm Baeder return Caller; 226*a07aba5dSTimm Baeder return S.getSplitFrame(); 227*a07aba5dSTimm Baeder } 228*a07aba5dSTimm Baeder 229*a07aba5dSTimm Baeder SourceRange InterpFrame::getCallRange() const { 230*a07aba5dSTimm Baeder if (!Caller->Func) { 231*a07aba5dSTimm Baeder if (SourceRange NullRange = S.getRange(nullptr, {}); NullRange.isValid()) 232*a07aba5dSTimm Baeder return NullRange; 233*a07aba5dSTimm Baeder return S.EvalLocation; 234*a07aba5dSTimm Baeder } 235*a07aba5dSTimm Baeder return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t)); 236*a07aba5dSTimm Baeder } 237*a07aba5dSTimm Baeder 238*a07aba5dSTimm Baeder const FunctionDecl *InterpFrame::getCallee() const { 239*a07aba5dSTimm Baeder if (!Func) 240*a07aba5dSTimm Baeder return nullptr; 241*a07aba5dSTimm Baeder return Func->getDecl(); 242*a07aba5dSTimm Baeder } 243*a07aba5dSTimm Baeder 244*a07aba5dSTimm Baeder Pointer InterpFrame::getLocalPointer(unsigned Offset) const { 245*a07aba5dSTimm Baeder assert(Offset < Func->getFrameSize() && "Invalid local offset."); 246*a07aba5dSTimm Baeder return Pointer(localBlock(Offset)); 247*a07aba5dSTimm Baeder } 248*a07aba5dSTimm Baeder 249*a07aba5dSTimm Baeder Pointer InterpFrame::getParamPointer(unsigned Off) { 250*a07aba5dSTimm Baeder // Return the block if it was created previously. 251*a07aba5dSTimm Baeder if (auto Pt = Params.find(Off); Pt != Params.end()) 252*a07aba5dSTimm Baeder return Pointer(reinterpret_cast<Block *>(Pt->second.get())); 253*a07aba5dSTimm Baeder 254*a07aba5dSTimm Baeder // Allocate memory to store the parameter and the block metadata. 255*a07aba5dSTimm Baeder const auto &Desc = Func->getParamDescriptor(Off); 256*a07aba5dSTimm Baeder size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize(); 257*a07aba5dSTimm Baeder auto Memory = std::make_unique<char[]>(BlockSize); 258*a07aba5dSTimm Baeder auto *B = new (Memory.get()) Block(S.Ctx.getEvalID(), Desc.second); 259*a07aba5dSTimm Baeder B->invokeCtor(); 260*a07aba5dSTimm Baeder 261*a07aba5dSTimm Baeder // Copy the initial value. 262*a07aba5dSTimm Baeder TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off))); 263*a07aba5dSTimm Baeder 264*a07aba5dSTimm Baeder // Record the param. 265*a07aba5dSTimm Baeder Params.insert({Off, std::move(Memory)}); 266*a07aba5dSTimm Baeder return Pointer(B); 267*a07aba5dSTimm Baeder } 268*a07aba5dSTimm Baeder 269*a07aba5dSTimm Baeder SourceInfo InterpFrame::getSource(CodePtr PC) const { 270*a07aba5dSTimm Baeder // Implicitly created functions don't have any code we could point at, 271*a07aba5dSTimm Baeder // so return the call site. 272*a07aba5dSTimm Baeder if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) 273*a07aba5dSTimm Baeder return Caller->getSource(RetPC); 274*a07aba5dSTimm Baeder 275*a07aba5dSTimm Baeder return S.getSource(Func, PC); 276*a07aba5dSTimm Baeder } 277*a07aba5dSTimm Baeder 278*a07aba5dSTimm Baeder const Expr *InterpFrame::getExpr(CodePtr PC) const { 279*a07aba5dSTimm Baeder if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) 280*a07aba5dSTimm Baeder return Caller->getExpr(RetPC); 281*a07aba5dSTimm Baeder 282*a07aba5dSTimm Baeder return S.getExpr(Func, PC); 283*a07aba5dSTimm Baeder } 284*a07aba5dSTimm Baeder 285*a07aba5dSTimm Baeder SourceLocation InterpFrame::getLocation(CodePtr PC) const { 286*a07aba5dSTimm Baeder if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) 287*a07aba5dSTimm Baeder return Caller->getLocation(RetPC); 288*a07aba5dSTimm Baeder 289*a07aba5dSTimm Baeder return S.getLocation(Func, PC); 290*a07aba5dSTimm Baeder } 291*a07aba5dSTimm Baeder 292*a07aba5dSTimm Baeder SourceRange InterpFrame::getRange(CodePtr PC) const { 293*a07aba5dSTimm Baeder if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) 294*a07aba5dSTimm Baeder return Caller->getRange(RetPC); 295*a07aba5dSTimm Baeder 296*a07aba5dSTimm Baeder return S.getRange(Func, PC); 297*a07aba5dSTimm Baeder } 298