1a07aba5dSTimm Baeder //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder 9a07aba5dSTimm Baeder #include "Context.h" 10a07aba5dSTimm Baeder #include "ByteCodeEmitter.h" 11a07aba5dSTimm Baeder #include "Compiler.h" 12a07aba5dSTimm Baeder #include "EvalEmitter.h" 13a07aba5dSTimm Baeder #include "Interp.h" 14a07aba5dSTimm Baeder #include "InterpFrame.h" 15a07aba5dSTimm Baeder #include "InterpStack.h" 16a07aba5dSTimm Baeder #include "PrimType.h" 17a07aba5dSTimm Baeder #include "Program.h" 18a07aba5dSTimm Baeder #include "clang/AST/Expr.h" 19a07aba5dSTimm Baeder #include "clang/Basic/TargetInfo.h" 20a07aba5dSTimm Baeder 21a07aba5dSTimm Baeder using namespace clang; 22a07aba5dSTimm Baeder using namespace clang::interp; 23a07aba5dSTimm Baeder 24a07aba5dSTimm Baeder Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 25a07aba5dSTimm Baeder 26a07aba5dSTimm Baeder Context::~Context() {} 27a07aba5dSTimm Baeder 28a07aba5dSTimm Baeder bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 29a07aba5dSTimm Baeder assert(Stk.empty()); 30*2c934dc5STimm Baeder const Function *Func = getOrCreateFunction(FD); 31a07aba5dSTimm Baeder if (!Func) 32a07aba5dSTimm Baeder return false; 33a07aba5dSTimm Baeder 3482ed9c03STimm Baeder if (!Run(Parent, Func)) 35a07aba5dSTimm Baeder return false; 36a07aba5dSTimm Baeder 37a07aba5dSTimm Baeder return Func->isConstexpr(); 38a07aba5dSTimm Baeder } 39a07aba5dSTimm Baeder 40a07aba5dSTimm Baeder bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 41a07aba5dSTimm Baeder ++EvalID; 42a07aba5dSTimm Baeder bool Recursing = !Stk.empty(); 43eef8116bSTimm Baeder size_t StackSizeBefore = Stk.size(); 44a07aba5dSTimm Baeder Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 45a07aba5dSTimm Baeder 46a07aba5dSTimm Baeder auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue()); 47a07aba5dSTimm Baeder 48a07aba5dSTimm Baeder if (Res.isInvalid()) { 49a07aba5dSTimm Baeder C.cleanup(); 50eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 51a07aba5dSTimm Baeder return false; 52a07aba5dSTimm Baeder } 53a07aba5dSTimm Baeder 54a07aba5dSTimm Baeder if (!Recursing) { 55a07aba5dSTimm Baeder assert(Stk.empty()); 56a07aba5dSTimm Baeder C.cleanup(); 57a07aba5dSTimm Baeder #ifndef NDEBUG 58a07aba5dSTimm Baeder // Make sure we don't rely on some value being still alive in 59a07aba5dSTimm Baeder // InterpStack memory. 60eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 61a07aba5dSTimm Baeder #endif 62a07aba5dSTimm Baeder } 63a07aba5dSTimm Baeder 64a07aba5dSTimm Baeder Result = Res.toAPValue(); 65a07aba5dSTimm Baeder 66a07aba5dSTimm Baeder return true; 67a07aba5dSTimm Baeder } 68a07aba5dSTimm Baeder 6983fea8b8STimm Baeder bool Context::evaluate(State &Parent, const Expr *E, APValue &Result, 7083fea8b8STimm Baeder ConstantExprKind Kind) { 71a07aba5dSTimm Baeder ++EvalID; 72a07aba5dSTimm Baeder bool Recursing = !Stk.empty(); 73eef8116bSTimm Baeder size_t StackSizeBefore = Stk.size(); 74a07aba5dSTimm Baeder Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 75a07aba5dSTimm Baeder 7683fea8b8STimm Baeder auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false, 773eaf4a9dSTimm Baeder /*DestroyToplevelScope=*/true); 78a07aba5dSTimm Baeder if (Res.isInvalid()) { 79a07aba5dSTimm Baeder C.cleanup(); 80eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 81a07aba5dSTimm Baeder return false; 82a07aba5dSTimm Baeder } 83a07aba5dSTimm Baeder 84a07aba5dSTimm Baeder if (!Recursing) { 85a07aba5dSTimm Baeder assert(Stk.empty()); 86a07aba5dSTimm Baeder C.cleanup(); 87a07aba5dSTimm Baeder #ifndef NDEBUG 88a07aba5dSTimm Baeder // Make sure we don't rely on some value being still alive in 89a07aba5dSTimm Baeder // InterpStack memory. 90eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 91a07aba5dSTimm Baeder #endif 92a07aba5dSTimm Baeder } 93a07aba5dSTimm Baeder 94a07aba5dSTimm Baeder Result = Res.toAPValue(); 95a07aba5dSTimm Baeder return true; 96a07aba5dSTimm Baeder } 97a07aba5dSTimm Baeder 98a07aba5dSTimm Baeder bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 99a07aba5dSTimm Baeder APValue &Result) { 100a07aba5dSTimm Baeder ++EvalID; 101a07aba5dSTimm Baeder bool Recursing = !Stk.empty(); 102eef8116bSTimm Baeder size_t StackSizeBefore = Stk.size(); 103a07aba5dSTimm Baeder Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 104a07aba5dSTimm Baeder 105a07aba5dSTimm Baeder bool CheckGlobalInitialized = 106a07aba5dSTimm Baeder shouldBeGloballyIndexed(VD) && 107a07aba5dSTimm Baeder (VD->getType()->isRecordType() || VD->getType()->isArrayType()); 108a07aba5dSTimm Baeder auto Res = C.interpretDecl(VD, CheckGlobalInitialized); 109a07aba5dSTimm Baeder if (Res.isInvalid()) { 110a07aba5dSTimm Baeder C.cleanup(); 111eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 112eef8116bSTimm Baeder 113a07aba5dSTimm Baeder return false; 114a07aba5dSTimm Baeder } 115a07aba5dSTimm Baeder 116a07aba5dSTimm Baeder if (!Recursing) { 117a07aba5dSTimm Baeder assert(Stk.empty()); 118a07aba5dSTimm Baeder C.cleanup(); 119a07aba5dSTimm Baeder #ifndef NDEBUG 120a07aba5dSTimm Baeder // Make sure we don't rely on some value being still alive in 121a07aba5dSTimm Baeder // InterpStack memory. 122eef8116bSTimm Baeder Stk.clearTo(StackSizeBefore); 123a07aba5dSTimm Baeder #endif 124a07aba5dSTimm Baeder } 125a07aba5dSTimm Baeder 126a07aba5dSTimm Baeder Result = Res.toAPValue(); 127a07aba5dSTimm Baeder return true; 128a07aba5dSTimm Baeder } 129a07aba5dSTimm Baeder 130a07aba5dSTimm Baeder const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 131a07aba5dSTimm Baeder 132a07aba5dSTimm Baeder std::optional<PrimType> Context::classify(QualType T) const { 133a07aba5dSTimm Baeder if (T->isBooleanType()) 134a07aba5dSTimm Baeder return PT_Bool; 135a07aba5dSTimm Baeder 136a07aba5dSTimm Baeder // We map these to primitive arrays. 137a07aba5dSTimm Baeder if (T->isAnyComplexType() || T->isVectorType()) 138a07aba5dSTimm Baeder return std::nullopt; 139a07aba5dSTimm Baeder 140a07aba5dSTimm Baeder if (T->isSignedIntegerOrEnumerationType()) { 141a07aba5dSTimm Baeder switch (Ctx.getIntWidth(T)) { 142a07aba5dSTimm Baeder case 64: 143a07aba5dSTimm Baeder return PT_Sint64; 144a07aba5dSTimm Baeder case 32: 145a07aba5dSTimm Baeder return PT_Sint32; 146a07aba5dSTimm Baeder case 16: 147a07aba5dSTimm Baeder return PT_Sint16; 148a07aba5dSTimm Baeder case 8: 149a07aba5dSTimm Baeder return PT_Sint8; 150a07aba5dSTimm Baeder default: 151a07aba5dSTimm Baeder return PT_IntAPS; 152a07aba5dSTimm Baeder } 153a07aba5dSTimm Baeder } 154a07aba5dSTimm Baeder 155a07aba5dSTimm Baeder if (T->isUnsignedIntegerOrEnumerationType()) { 156a07aba5dSTimm Baeder switch (Ctx.getIntWidth(T)) { 157a07aba5dSTimm Baeder case 64: 158a07aba5dSTimm Baeder return PT_Uint64; 159a07aba5dSTimm Baeder case 32: 160a07aba5dSTimm Baeder return PT_Uint32; 161a07aba5dSTimm Baeder case 16: 162a07aba5dSTimm Baeder return PT_Uint16; 163a07aba5dSTimm Baeder case 8: 164a07aba5dSTimm Baeder return PT_Uint8; 165f620c5b6STimm Baeder case 1: 166f620c5b6STimm Baeder // Might happen for enum types. 167f620c5b6STimm Baeder return PT_Bool; 168a07aba5dSTimm Baeder default: 169a07aba5dSTimm Baeder return PT_IntAP; 170a07aba5dSTimm Baeder } 171a07aba5dSTimm Baeder } 172a07aba5dSTimm Baeder 173a07aba5dSTimm Baeder if (T->isNullPtrType()) 174a07aba5dSTimm Baeder return PT_Ptr; 175a07aba5dSTimm Baeder 176a07aba5dSTimm Baeder if (T->isFloatingType()) 177a07aba5dSTimm Baeder return PT_Float; 178a07aba5dSTimm Baeder 179a07aba5dSTimm Baeder if (T->isSpecificBuiltinType(BuiltinType::BoundMember) || 180a07aba5dSTimm Baeder T->isMemberPointerType()) 181a07aba5dSTimm Baeder return PT_MemberPtr; 182a07aba5dSTimm Baeder 183a07aba5dSTimm Baeder if (T->isFunctionPointerType() || T->isFunctionReferenceType() || 184ca148b21STimm Baeder T->isFunctionType() || T->isBlockPointerType()) 185a07aba5dSTimm Baeder return PT_FnPtr; 186a07aba5dSTimm Baeder 187a07aba5dSTimm Baeder if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) 188a07aba5dSTimm Baeder return PT_Ptr; 189a07aba5dSTimm Baeder 190a07aba5dSTimm Baeder if (const auto *AT = T->getAs<AtomicType>()) 191a07aba5dSTimm Baeder return classify(AT->getValueType()); 192a07aba5dSTimm Baeder 193a07aba5dSTimm Baeder if (const auto *DT = dyn_cast<DecltypeType>(T)) 194a07aba5dSTimm Baeder return classify(DT->getUnderlyingType()); 195a07aba5dSTimm Baeder 196048bc672STimm Baeder if (T->isFixedPointType()) 197048bc672STimm Baeder return PT_FixedPoint; 198048bc672STimm Baeder 199a07aba5dSTimm Baeder return std::nullopt; 200a07aba5dSTimm Baeder } 201a07aba5dSTimm Baeder 202a07aba5dSTimm Baeder unsigned Context::getCharBit() const { 203a07aba5dSTimm Baeder return Ctx.getTargetInfo().getCharWidth(); 204a07aba5dSTimm Baeder } 205a07aba5dSTimm Baeder 206a07aba5dSTimm Baeder /// Simple wrapper around getFloatTypeSemantics() to make code a 207a07aba5dSTimm Baeder /// little shorter. 208a07aba5dSTimm Baeder const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { 209a07aba5dSTimm Baeder return Ctx.getFloatTypeSemantics(T); 210a07aba5dSTimm Baeder } 211a07aba5dSTimm Baeder 21282ed9c03STimm Baeder bool Context::Run(State &Parent, const Function *Func) { 213a07aba5dSTimm Baeder 214a07aba5dSTimm Baeder { 215a07aba5dSTimm Baeder InterpState State(Parent, *P, Stk, *this); 216a07aba5dSTimm Baeder State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(), 217a07aba5dSTimm Baeder Func->getArgSize()); 21882ed9c03STimm Baeder if (Interpret(State)) { 219a07aba5dSTimm Baeder assert(Stk.empty()); 220a07aba5dSTimm Baeder return true; 221a07aba5dSTimm Baeder } 222a07aba5dSTimm Baeder 223a07aba5dSTimm Baeder // State gets destroyed here, so the Stk.clear() below doesn't accidentally 224a07aba5dSTimm Baeder // remove values the State's destructor might access. 225a07aba5dSTimm Baeder } 226a07aba5dSTimm Baeder 227a07aba5dSTimm Baeder Stk.clear(); 228a07aba5dSTimm Baeder return false; 229a07aba5dSTimm Baeder } 230a07aba5dSTimm Baeder 231a07aba5dSTimm Baeder // TODO: Virtual bases? 232a07aba5dSTimm Baeder const CXXMethodDecl * 233a07aba5dSTimm Baeder Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, 234a07aba5dSTimm Baeder const CXXRecordDecl *StaticDecl, 235a07aba5dSTimm Baeder const CXXMethodDecl *InitialFunction) const { 236a07aba5dSTimm Baeder assert(DynamicDecl); 237a07aba5dSTimm Baeder assert(StaticDecl); 238a07aba5dSTimm Baeder assert(InitialFunction); 239a07aba5dSTimm Baeder 240a07aba5dSTimm Baeder const CXXRecordDecl *CurRecord = DynamicDecl; 241a07aba5dSTimm Baeder const CXXMethodDecl *FoundFunction = InitialFunction; 242a07aba5dSTimm Baeder for (;;) { 243a07aba5dSTimm Baeder const CXXMethodDecl *Overrider = 244a07aba5dSTimm Baeder FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); 245a07aba5dSTimm Baeder if (Overrider) 246a07aba5dSTimm Baeder return Overrider; 247a07aba5dSTimm Baeder 248a07aba5dSTimm Baeder // Common case of only one base class. 249a07aba5dSTimm Baeder if (CurRecord->getNumBases() == 1) { 250a07aba5dSTimm Baeder CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); 251a07aba5dSTimm Baeder continue; 252a07aba5dSTimm Baeder } 253a07aba5dSTimm Baeder 254a07aba5dSTimm Baeder // Otherwise, go to the base class that will lead to the StaticDecl. 255a07aba5dSTimm Baeder for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { 256a07aba5dSTimm Baeder const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); 257a07aba5dSTimm Baeder if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { 258a07aba5dSTimm Baeder CurRecord = Base; 259a07aba5dSTimm Baeder break; 260a07aba5dSTimm Baeder } 261a07aba5dSTimm Baeder } 262a07aba5dSTimm Baeder } 263a07aba5dSTimm Baeder 264a07aba5dSTimm Baeder llvm_unreachable( 265a07aba5dSTimm Baeder "Couldn't find an overriding function in the class hierarchy?"); 266a07aba5dSTimm Baeder return nullptr; 267a07aba5dSTimm Baeder } 268a07aba5dSTimm Baeder 269a07aba5dSTimm Baeder const Function *Context::getOrCreateFunction(const FunctionDecl *FD) { 270a07aba5dSTimm Baeder assert(FD); 271*2c934dc5STimm Baeder FD = FD->getMostRecentDecl(); 272a07aba5dSTimm Baeder const Function *Func = P->getFunction(FD); 273a07aba5dSTimm Baeder bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled(); 274a07aba5dSTimm Baeder bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined(); 275a07aba5dSTimm Baeder 276a07aba5dSTimm Baeder if (IsBeingCompiled) 277a07aba5dSTimm Baeder return Func; 278a07aba5dSTimm Baeder 279a07aba5dSTimm Baeder if (!Func || WasNotDefined) { 280a07aba5dSTimm Baeder if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD)) 281a07aba5dSTimm Baeder Func = F; 282a07aba5dSTimm Baeder } 283a07aba5dSTimm Baeder 284a07aba5dSTimm Baeder return Func; 285a07aba5dSTimm Baeder } 286a07aba5dSTimm Baeder 287a07aba5dSTimm Baeder unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl, 288a07aba5dSTimm Baeder const RecordDecl *DerivedDecl) const { 289a07aba5dSTimm Baeder assert(BaseDecl); 290a07aba5dSTimm Baeder assert(DerivedDecl); 291a07aba5dSTimm Baeder const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl); 292a07aba5dSTimm Baeder const RecordDecl *CurDecl = DerivedDecl; 293a07aba5dSTimm Baeder const Record *CurRecord = P->getOrCreateRecord(CurDecl); 294a07aba5dSTimm Baeder assert(CurDecl && FinalDecl); 295a07aba5dSTimm Baeder 296a07aba5dSTimm Baeder unsigned OffsetSum = 0; 297a07aba5dSTimm Baeder for (;;) { 298a07aba5dSTimm Baeder assert(CurRecord->getNumBases() > 0); 299a07aba5dSTimm Baeder // One level up 300a07aba5dSTimm Baeder for (const Record::Base &B : CurRecord->bases()) { 301a07aba5dSTimm Baeder const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); 302a07aba5dSTimm Baeder 303a07aba5dSTimm Baeder if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { 304a07aba5dSTimm Baeder OffsetSum += B.Offset; 305a07aba5dSTimm Baeder CurRecord = B.R; 306a07aba5dSTimm Baeder CurDecl = BaseDecl; 307a07aba5dSTimm Baeder break; 308a07aba5dSTimm Baeder } 309a07aba5dSTimm Baeder } 310a07aba5dSTimm Baeder if (CurDecl == FinalDecl) 311a07aba5dSTimm Baeder break; 312a07aba5dSTimm Baeder } 313a07aba5dSTimm Baeder 314a07aba5dSTimm Baeder assert(OffsetSum > 0); 315a07aba5dSTimm Baeder return OffsetSum; 316a07aba5dSTimm Baeder } 317a07aba5dSTimm Baeder 318a07aba5dSTimm Baeder const Record *Context::getRecord(const RecordDecl *D) const { 319a07aba5dSTimm Baeder return P->getOrCreateRecord(D); 320a07aba5dSTimm Baeder } 321