1a7dea167SDimitry Andric //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 9a7dea167SDimitry Andric #include "Context.h" 10a7dea167SDimitry Andric #include "ByteCodeEmitter.h" 11*0fca6ea1SDimitry Andric #include "Compiler.h" 12a7dea167SDimitry Andric #include "EvalEmitter.h" 13a7dea167SDimitry Andric #include "Interp.h" 14a7dea167SDimitry Andric #include "InterpFrame.h" 15a7dea167SDimitry Andric #include "InterpStack.h" 16a7dea167SDimitry Andric #include "PrimType.h" 17a7dea167SDimitry Andric #include "Program.h" 18a7dea167SDimitry Andric #include "clang/AST/Expr.h" 195ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h" 20a7dea167SDimitry Andric 21a7dea167SDimitry Andric using namespace clang; 22a7dea167SDimitry Andric using namespace clang::interp; 23a7dea167SDimitry Andric 24480093f4SDimitry Andric Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 25a7dea167SDimitry Andric 26a7dea167SDimitry Andric Context::~Context() {} 27a7dea167SDimitry Andric 28480093f4SDimitry Andric bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 29bdd1243dSDimitry Andric assert(Stk.empty()); 30a7dea167SDimitry Andric Function *Func = P->getFunction(FD); 317a6dacacSDimitry Andric if (!Func || !Func->hasBody()) 32*0fca6ea1SDimitry Andric Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD); 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric if (!Func) 35*0fca6ea1SDimitry Andric return false; 36a7dea167SDimitry Andric 3706c3fb27SDimitry Andric APValue DummyResult; 38*0fca6ea1SDimitry Andric if (!Run(Parent, Func, DummyResult)) 3906c3fb27SDimitry Andric return false; 4006c3fb27SDimitry Andric 41bdd1243dSDimitry Andric return Func->isConstexpr(); 42a7dea167SDimitry Andric } 43a7dea167SDimitry Andric 44480093f4SDimitry Andric bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 45*0fca6ea1SDimitry Andric ++EvalID; 46*0fca6ea1SDimitry Andric bool Recursing = !Stk.empty(); 47*0fca6ea1SDimitry Andric Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 487a6dacacSDimitry Andric 49*0fca6ea1SDimitry Andric auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue()); 507a6dacacSDimitry Andric 517a6dacacSDimitry Andric if (Res.isInvalid()) { 52*0fca6ea1SDimitry Andric C.cleanup(); 537a6dacacSDimitry Andric Stk.clear(); 547a6dacacSDimitry Andric return false; 557a6dacacSDimitry Andric } 567a6dacacSDimitry Andric 57*0fca6ea1SDimitry Andric if (!Recursing) { 58bdd1243dSDimitry Andric assert(Stk.empty()); 5906c3fb27SDimitry Andric #ifndef NDEBUG 6006c3fb27SDimitry Andric // Make sure we don't rely on some value being still alive in 6106c3fb27SDimitry Andric // InterpStack memory. 6206c3fb27SDimitry Andric Stk.clear(); 6306c3fb27SDimitry Andric #endif 64*0fca6ea1SDimitry Andric } 657a6dacacSDimitry Andric 667a6dacacSDimitry Andric Result = Res.toAPValue(); 677a6dacacSDimitry Andric 68bdd1243dSDimitry Andric return true; 69bdd1243dSDimitry Andric } 70bdd1243dSDimitry Andric 717a6dacacSDimitry Andric bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) { 72*0fca6ea1SDimitry Andric ++EvalID; 73*0fca6ea1SDimitry Andric bool Recursing = !Stk.empty(); 74*0fca6ea1SDimitry Andric Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 757a6dacacSDimitry Andric 767a6dacacSDimitry Andric auto Res = C.interpretExpr(E); 777a6dacacSDimitry Andric if (Res.isInvalid()) { 78*0fca6ea1SDimitry Andric C.cleanup(); 79bdd1243dSDimitry Andric Stk.clear(); 80bdd1243dSDimitry Andric return false; 81a7dea167SDimitry Andric } 82a7dea167SDimitry Andric 83*0fca6ea1SDimitry Andric if (!Recursing) { 847a6dacacSDimitry Andric assert(Stk.empty()); 857a6dacacSDimitry Andric #ifndef NDEBUG 867a6dacacSDimitry Andric // Make sure we don't rely on some value being still alive in 877a6dacacSDimitry Andric // InterpStack memory. 887a6dacacSDimitry Andric Stk.clear(); 897a6dacacSDimitry Andric #endif 90*0fca6ea1SDimitry Andric } 91*0fca6ea1SDimitry Andric 927a6dacacSDimitry Andric Result = Res.toAPValue(); 937a6dacacSDimitry Andric return true; 947a6dacacSDimitry Andric } 957a6dacacSDimitry Andric 96480093f4SDimitry Andric bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 97a7dea167SDimitry Andric APValue &Result) { 98*0fca6ea1SDimitry Andric ++EvalID; 99*0fca6ea1SDimitry Andric bool Recursing = !Stk.empty(); 100*0fca6ea1SDimitry Andric Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 1017a6dacacSDimitry Andric 102*0fca6ea1SDimitry Andric bool CheckGlobalInitialized = 103*0fca6ea1SDimitry Andric shouldBeGloballyIndexed(VD) && 104*0fca6ea1SDimitry Andric (VD->getType()->isRecordType() || VD->getType()->isArrayType()); 105*0fca6ea1SDimitry Andric auto Res = C.interpretDecl(VD, CheckGlobalInitialized); 1067a6dacacSDimitry Andric if (Res.isInvalid()) { 107*0fca6ea1SDimitry Andric C.cleanup(); 1087a6dacacSDimitry Andric Stk.clear(); 1097a6dacacSDimitry Andric return false; 1107a6dacacSDimitry Andric } 1117a6dacacSDimitry Andric 112*0fca6ea1SDimitry Andric if (!Recursing) { 113bdd1243dSDimitry Andric assert(Stk.empty()); 11406c3fb27SDimitry Andric #ifndef NDEBUG 11506c3fb27SDimitry Andric // Make sure we don't rely on some value being still alive in 11606c3fb27SDimitry Andric // InterpStack memory. 11706c3fb27SDimitry Andric Stk.clear(); 11806c3fb27SDimitry Andric #endif 119*0fca6ea1SDimitry Andric } 120bdd1243dSDimitry Andric 1217a6dacacSDimitry Andric Result = Res.toAPValue(); 1227a6dacacSDimitry Andric return true; 123a7dea167SDimitry Andric } 124a7dea167SDimitry Andric 125a7dea167SDimitry Andric const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 126a7dea167SDimitry Andric 127bdd1243dSDimitry Andric std::optional<PrimType> Context::classify(QualType T) const { 128a7dea167SDimitry Andric if (T->isBooleanType()) 129a7dea167SDimitry Andric return PT_Bool; 130a7dea167SDimitry Andric 131*0fca6ea1SDimitry Andric // We map these to primitive arrays. 132*0fca6ea1SDimitry Andric if (T->isAnyComplexType() || T->isVectorType()) 1335f757f3fSDimitry Andric return std::nullopt; 1345f757f3fSDimitry Andric 135a7dea167SDimitry Andric if (T->isSignedIntegerOrEnumerationType()) { 136a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 137a7dea167SDimitry Andric case 64: 138a7dea167SDimitry Andric return PT_Sint64; 139a7dea167SDimitry Andric case 32: 140a7dea167SDimitry Andric return PT_Sint32; 141a7dea167SDimitry Andric case 16: 142a7dea167SDimitry Andric return PT_Sint16; 143a7dea167SDimitry Andric case 8: 144a7dea167SDimitry Andric return PT_Sint8; 145a7dea167SDimitry Andric default: 1465f757f3fSDimitry Andric return PT_IntAPS; 147a7dea167SDimitry Andric } 148a7dea167SDimitry Andric } 149a7dea167SDimitry Andric 150a7dea167SDimitry Andric if (T->isUnsignedIntegerOrEnumerationType()) { 151a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 152a7dea167SDimitry Andric case 64: 153a7dea167SDimitry Andric return PT_Uint64; 154a7dea167SDimitry Andric case 32: 155a7dea167SDimitry Andric return PT_Uint32; 156a7dea167SDimitry Andric case 16: 157a7dea167SDimitry Andric return PT_Uint16; 158a7dea167SDimitry Andric case 8: 159a7dea167SDimitry Andric return PT_Uint8; 160a7dea167SDimitry Andric default: 1615f757f3fSDimitry Andric return PT_IntAP; 162a7dea167SDimitry Andric } 163a7dea167SDimitry Andric } 164a7dea167SDimitry Andric 165a7dea167SDimitry Andric if (T->isNullPtrType()) 166a7dea167SDimitry Andric return PT_Ptr; 167a7dea167SDimitry Andric 16806c3fb27SDimitry Andric if (T->isFloatingType()) 16906c3fb27SDimitry Andric return PT_Float; 17006c3fb27SDimitry Andric 171*0fca6ea1SDimitry Andric if (T->isSpecificBuiltinType(BuiltinType::BoundMember) || 172*0fca6ea1SDimitry Andric T->isMemberPointerType()) 173*0fca6ea1SDimitry Andric return PT_MemberPtr; 174*0fca6ea1SDimitry Andric 1755f757f3fSDimitry Andric if (T->isFunctionPointerType() || T->isFunctionReferenceType() || 176*0fca6ea1SDimitry Andric T->isFunctionType()) 1775f757f3fSDimitry Andric return PT_FnPtr; 1785f757f3fSDimitry Andric 179*0fca6ea1SDimitry Andric if (T->isReferenceType() || T->isPointerType() || 180*0fca6ea1SDimitry Andric T->isObjCObjectPointerType()) 1815f757f3fSDimitry Andric return PT_Ptr; 1825f757f3fSDimitry Andric 183*0fca6ea1SDimitry Andric if (const auto *AT = T->getAs<AtomicType>()) 184a7dea167SDimitry Andric return classify(AT->getValueType()); 185a7dea167SDimitry Andric 1865f757f3fSDimitry Andric if (const auto *DT = dyn_cast<DecltypeType>(T)) 1875f757f3fSDimitry Andric return classify(DT->getUnderlyingType()); 1885f757f3fSDimitry Andric 1895f757f3fSDimitry Andric return std::nullopt; 190a7dea167SDimitry Andric } 191a7dea167SDimitry Andric 192a7dea167SDimitry Andric unsigned Context::getCharBit() const { 193a7dea167SDimitry Andric return Ctx.getTargetInfo().getCharWidth(); 194a7dea167SDimitry Andric } 195a7dea167SDimitry Andric 19606c3fb27SDimitry Andric /// Simple wrapper around getFloatTypeSemantics() to make code a 19706c3fb27SDimitry Andric /// little shorter. 19806c3fb27SDimitry Andric const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { 19906c3fb27SDimitry Andric return Ctx.getFloatTypeSemantics(T); 20006c3fb27SDimitry Andric } 20106c3fb27SDimitry Andric 20206c3fb27SDimitry Andric bool Context::Run(State &Parent, const Function *Func, APValue &Result) { 2035f757f3fSDimitry Andric 2045f757f3fSDimitry Andric { 205a7dea167SDimitry Andric InterpState State(Parent, *P, Stk, *this); 206*0fca6ea1SDimitry Andric State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(), 207*0fca6ea1SDimitry Andric Func->getArgSize()); 2085f757f3fSDimitry Andric if (Interpret(State, Result)) { 2095f757f3fSDimitry Andric assert(Stk.empty()); 210480093f4SDimitry Andric return true; 2115f757f3fSDimitry Andric } 2125f757f3fSDimitry Andric 2135f757f3fSDimitry Andric // State gets destroyed here, so the Stk.clear() below doesn't accidentally 2145f757f3fSDimitry Andric // remove values the State's destructor might access. 2155f757f3fSDimitry Andric } 2165f757f3fSDimitry Andric 217a7dea167SDimitry Andric Stk.clear(); 218480093f4SDimitry Andric return false; 219a7dea167SDimitry Andric } 220a7dea167SDimitry Andric 22106c3fb27SDimitry Andric // TODO: Virtual bases? 22206c3fb27SDimitry Andric const CXXMethodDecl * 22306c3fb27SDimitry Andric Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, 22406c3fb27SDimitry Andric const CXXRecordDecl *StaticDecl, 22506c3fb27SDimitry Andric const CXXMethodDecl *InitialFunction) const { 226*0fca6ea1SDimitry Andric assert(DynamicDecl); 227*0fca6ea1SDimitry Andric assert(StaticDecl); 228*0fca6ea1SDimitry Andric assert(InitialFunction); 22906c3fb27SDimitry Andric 23006c3fb27SDimitry Andric const CXXRecordDecl *CurRecord = DynamicDecl; 23106c3fb27SDimitry Andric const CXXMethodDecl *FoundFunction = InitialFunction; 23206c3fb27SDimitry Andric for (;;) { 23306c3fb27SDimitry Andric const CXXMethodDecl *Overrider = 23406c3fb27SDimitry Andric FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); 23506c3fb27SDimitry Andric if (Overrider) 23606c3fb27SDimitry Andric return Overrider; 23706c3fb27SDimitry Andric 23806c3fb27SDimitry Andric // Common case of only one base class. 23906c3fb27SDimitry Andric if (CurRecord->getNumBases() == 1) { 24006c3fb27SDimitry Andric CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); 24106c3fb27SDimitry Andric continue; 24206c3fb27SDimitry Andric } 24306c3fb27SDimitry Andric 24406c3fb27SDimitry Andric // Otherwise, go to the base class that will lead to the StaticDecl. 24506c3fb27SDimitry Andric for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { 24606c3fb27SDimitry Andric const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); 24706c3fb27SDimitry Andric if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { 24806c3fb27SDimitry Andric CurRecord = Base; 24906c3fb27SDimitry Andric break; 25006c3fb27SDimitry Andric } 25106c3fb27SDimitry Andric } 25206c3fb27SDimitry Andric } 25306c3fb27SDimitry Andric 25406c3fb27SDimitry Andric llvm_unreachable( 25506c3fb27SDimitry Andric "Couldn't find an overriding function in the class hierarchy?"); 25606c3fb27SDimitry Andric return nullptr; 25706c3fb27SDimitry Andric } 2585f757f3fSDimitry Andric 2595f757f3fSDimitry Andric const Function *Context::getOrCreateFunction(const FunctionDecl *FD) { 2605f757f3fSDimitry Andric assert(FD); 2615f757f3fSDimitry Andric const Function *Func = P->getFunction(FD); 2625f757f3fSDimitry Andric bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled(); 2635f757f3fSDimitry Andric bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined(); 2645f757f3fSDimitry Andric 2655f757f3fSDimitry Andric if (IsBeingCompiled) 2665f757f3fSDimitry Andric return Func; 2675f757f3fSDimitry Andric 2685f757f3fSDimitry Andric if (!Func || WasNotDefined) { 269*0fca6ea1SDimitry Andric if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD)) 2707a6dacacSDimitry Andric Func = F; 2715f757f3fSDimitry Andric } 2725f757f3fSDimitry Andric 2735f757f3fSDimitry Andric return Func; 2745f757f3fSDimitry Andric } 275*0fca6ea1SDimitry Andric 276*0fca6ea1SDimitry Andric unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl, 277*0fca6ea1SDimitry Andric const RecordDecl *DerivedDecl) const { 278*0fca6ea1SDimitry Andric assert(BaseDecl); 279*0fca6ea1SDimitry Andric assert(DerivedDecl); 280*0fca6ea1SDimitry Andric const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl); 281*0fca6ea1SDimitry Andric const RecordDecl *CurDecl = DerivedDecl; 282*0fca6ea1SDimitry Andric const Record *CurRecord = P->getOrCreateRecord(CurDecl); 283*0fca6ea1SDimitry Andric assert(CurDecl && FinalDecl); 284*0fca6ea1SDimitry Andric 285*0fca6ea1SDimitry Andric unsigned OffsetSum = 0; 286*0fca6ea1SDimitry Andric for (;;) { 287*0fca6ea1SDimitry Andric assert(CurRecord->getNumBases() > 0); 288*0fca6ea1SDimitry Andric // One level up 289*0fca6ea1SDimitry Andric for (const Record::Base &B : CurRecord->bases()) { 290*0fca6ea1SDimitry Andric const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); 291*0fca6ea1SDimitry Andric 292*0fca6ea1SDimitry Andric if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { 293*0fca6ea1SDimitry Andric OffsetSum += B.Offset; 294*0fca6ea1SDimitry Andric CurRecord = B.R; 295*0fca6ea1SDimitry Andric CurDecl = BaseDecl; 296*0fca6ea1SDimitry Andric break; 297*0fca6ea1SDimitry Andric } 298*0fca6ea1SDimitry Andric } 299*0fca6ea1SDimitry Andric if (CurDecl == FinalDecl) 300*0fca6ea1SDimitry Andric break; 301*0fca6ea1SDimitry Andric } 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric assert(OffsetSum > 0); 304*0fca6ea1SDimitry Andric return OffsetSum; 305*0fca6ea1SDimitry Andric } 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric const Record *Context::getRecord(const RecordDecl *D) const { 308*0fca6ea1SDimitry Andric return P->getOrCreateRecord(D); 309*0fca6ea1SDimitry Andric } 310