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" 11a7dea167SDimitry Andric #include "ByteCodeExprGen.h" 12*5f757f3fSDimitry Andric #include "ByteCodeGenError.h" 13a7dea167SDimitry Andric #include "ByteCodeStmtGen.h" 14a7dea167SDimitry Andric #include "EvalEmitter.h" 15a7dea167SDimitry Andric #include "Interp.h" 16a7dea167SDimitry Andric #include "InterpFrame.h" 17a7dea167SDimitry Andric #include "InterpStack.h" 18a7dea167SDimitry Andric #include "PrimType.h" 19a7dea167SDimitry Andric #include "Program.h" 20a7dea167SDimitry Andric #include "clang/AST/Expr.h" 215ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h" 22a7dea167SDimitry Andric 23a7dea167SDimitry Andric using namespace clang; 24a7dea167SDimitry Andric using namespace clang::interp; 25a7dea167SDimitry Andric 26480093f4SDimitry Andric Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 27a7dea167SDimitry Andric 28a7dea167SDimitry Andric Context::~Context() {} 29a7dea167SDimitry Andric 30480093f4SDimitry Andric bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 31bdd1243dSDimitry Andric assert(Stk.empty()); 32a7dea167SDimitry Andric Function *Func = P->getFunction(FD); 33bdd1243dSDimitry Andric if (!Func || !Func->hasBody()) { 34a7dea167SDimitry Andric if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) { 35a7dea167SDimitry Andric Func = *R; 36480093f4SDimitry Andric } else { 37a7dea167SDimitry Andric handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) { 38bdd1243dSDimitry Andric Parent.FFDiag(Err.getRange().getBegin(), 39bdd1243dSDimitry Andric diag::err_experimental_clang_interp_failed) 40bdd1243dSDimitry Andric << Err.getRange(); 41a7dea167SDimitry Andric }); 42480093f4SDimitry Andric return false; 43a7dea167SDimitry Andric } 44a7dea167SDimitry Andric } 45a7dea167SDimitry Andric 4606c3fb27SDimitry Andric APValue DummyResult; 4706c3fb27SDimitry Andric if (!Run(Parent, Func, DummyResult)) { 4806c3fb27SDimitry Andric return false; 4906c3fb27SDimitry Andric } 5006c3fb27SDimitry Andric 51bdd1243dSDimitry Andric return Func->isConstexpr(); 52a7dea167SDimitry Andric } 53a7dea167SDimitry Andric 54480093f4SDimitry Andric bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 55bdd1243dSDimitry Andric assert(Stk.empty()); 56a7dea167SDimitry Andric ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 57bdd1243dSDimitry Andric if (Check(Parent, C.interpretExpr(E))) { 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 64bdd1243dSDimitry Andric return true; 65bdd1243dSDimitry Andric } 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric Stk.clear(); 68bdd1243dSDimitry Andric return false; 69a7dea167SDimitry Andric } 70a7dea167SDimitry Andric 71480093f4SDimitry Andric bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 72a7dea167SDimitry Andric APValue &Result) { 73bdd1243dSDimitry Andric assert(Stk.empty()); 74a7dea167SDimitry Andric ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 75bdd1243dSDimitry Andric if (Check(Parent, C.interpretDecl(VD))) { 76bdd1243dSDimitry Andric assert(Stk.empty()); 7706c3fb27SDimitry Andric #ifndef NDEBUG 7806c3fb27SDimitry Andric // Make sure we don't rely on some value being still alive in 7906c3fb27SDimitry Andric // InterpStack memory. 8006c3fb27SDimitry Andric Stk.clear(); 8106c3fb27SDimitry Andric #endif 82bdd1243dSDimitry Andric return true; 83bdd1243dSDimitry Andric } 84bdd1243dSDimitry Andric 85bdd1243dSDimitry Andric Stk.clear(); 86bdd1243dSDimitry Andric return false; 87a7dea167SDimitry Andric } 88a7dea167SDimitry Andric 89a7dea167SDimitry Andric const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 90a7dea167SDimitry Andric 91bdd1243dSDimitry Andric std::optional<PrimType> Context::classify(QualType T) const { 92a7dea167SDimitry Andric if (T->isBooleanType()) 93a7dea167SDimitry Andric return PT_Bool; 94a7dea167SDimitry Andric 95*5f757f3fSDimitry Andric if (T->isAnyComplexType()) 96*5f757f3fSDimitry Andric return std::nullopt; 97*5f757f3fSDimitry Andric 98a7dea167SDimitry Andric if (T->isSignedIntegerOrEnumerationType()) { 99a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 100a7dea167SDimitry Andric case 64: 101a7dea167SDimitry Andric return PT_Sint64; 102a7dea167SDimitry Andric case 32: 103a7dea167SDimitry Andric return PT_Sint32; 104a7dea167SDimitry Andric case 16: 105a7dea167SDimitry Andric return PT_Sint16; 106a7dea167SDimitry Andric case 8: 107a7dea167SDimitry Andric return PT_Sint8; 108a7dea167SDimitry Andric default: 109*5f757f3fSDimitry Andric return PT_IntAPS; 110a7dea167SDimitry Andric } 111a7dea167SDimitry Andric } 112a7dea167SDimitry Andric 113a7dea167SDimitry Andric if (T->isUnsignedIntegerOrEnumerationType()) { 114a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 115a7dea167SDimitry Andric case 64: 116a7dea167SDimitry Andric return PT_Uint64; 117a7dea167SDimitry Andric case 32: 118a7dea167SDimitry Andric return PT_Uint32; 119a7dea167SDimitry Andric case 16: 120a7dea167SDimitry Andric return PT_Uint16; 121a7dea167SDimitry Andric case 8: 122a7dea167SDimitry Andric return PT_Uint8; 123a7dea167SDimitry Andric default: 124*5f757f3fSDimitry Andric return PT_IntAP; 125a7dea167SDimitry Andric } 126a7dea167SDimitry Andric } 127a7dea167SDimitry Andric 128a7dea167SDimitry Andric if (T->isNullPtrType()) 129a7dea167SDimitry Andric return PT_Ptr; 130a7dea167SDimitry Andric 13106c3fb27SDimitry Andric if (T->isFloatingType()) 13206c3fb27SDimitry Andric return PT_Float; 13306c3fb27SDimitry Andric 134*5f757f3fSDimitry Andric if (T->isFunctionPointerType() || T->isFunctionReferenceType() || 135*5f757f3fSDimitry Andric T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember)) 136*5f757f3fSDimitry Andric return PT_FnPtr; 137*5f757f3fSDimitry Andric 138*5f757f3fSDimitry Andric if (T->isReferenceType() || T->isPointerType()) 139*5f757f3fSDimitry Andric return PT_Ptr; 140*5f757f3fSDimitry Andric 141*5f757f3fSDimitry Andric if (const auto *AT = dyn_cast<AtomicType>(T)) 142a7dea167SDimitry Andric return classify(AT->getValueType()); 143a7dea167SDimitry Andric 144*5f757f3fSDimitry Andric if (const auto *DT = dyn_cast<DecltypeType>(T)) 145*5f757f3fSDimitry Andric return classify(DT->getUnderlyingType()); 146*5f757f3fSDimitry Andric 147*5f757f3fSDimitry Andric if (const auto *DT = dyn_cast<MemberPointerType>(T)) 148*5f757f3fSDimitry Andric return classify(DT->getPointeeType()); 149*5f757f3fSDimitry Andric 150*5f757f3fSDimitry Andric return std::nullopt; 151a7dea167SDimitry Andric } 152a7dea167SDimitry Andric 153a7dea167SDimitry Andric unsigned Context::getCharBit() const { 154a7dea167SDimitry Andric return Ctx.getTargetInfo().getCharWidth(); 155a7dea167SDimitry Andric } 156a7dea167SDimitry Andric 15706c3fb27SDimitry Andric /// Simple wrapper around getFloatTypeSemantics() to make code a 15806c3fb27SDimitry Andric /// little shorter. 15906c3fb27SDimitry Andric const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { 16006c3fb27SDimitry Andric return Ctx.getFloatTypeSemantics(T); 16106c3fb27SDimitry Andric } 16206c3fb27SDimitry Andric 16306c3fb27SDimitry Andric bool Context::Run(State &Parent, const Function *Func, APValue &Result) { 164*5f757f3fSDimitry Andric 165*5f757f3fSDimitry Andric { 166a7dea167SDimitry Andric InterpState State(Parent, *P, Stk, *this); 167bdd1243dSDimitry Andric State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {}); 168*5f757f3fSDimitry Andric if (Interpret(State, Result)) { 169*5f757f3fSDimitry Andric assert(Stk.empty()); 170480093f4SDimitry Andric return true; 171*5f757f3fSDimitry Andric } 172*5f757f3fSDimitry Andric 173*5f757f3fSDimitry Andric // State gets destroyed here, so the Stk.clear() below doesn't accidentally 174*5f757f3fSDimitry Andric // remove values the State's destructor might access. 175*5f757f3fSDimitry Andric } 176*5f757f3fSDimitry Andric 177a7dea167SDimitry Andric Stk.clear(); 178480093f4SDimitry Andric return false; 179a7dea167SDimitry Andric } 180a7dea167SDimitry Andric 181480093f4SDimitry Andric bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) { 182480093f4SDimitry Andric if (Flag) 183480093f4SDimitry Andric return *Flag; 184480093f4SDimitry Andric handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) { 185bdd1243dSDimitry Andric Parent.FFDiag(Err.getRange().getBegin(), 186bdd1243dSDimitry Andric diag::err_experimental_clang_interp_failed) 187bdd1243dSDimitry Andric << Err.getRange(); 188a7dea167SDimitry Andric }); 189480093f4SDimitry Andric return false; 190a7dea167SDimitry Andric } 19106c3fb27SDimitry Andric 19206c3fb27SDimitry Andric // TODO: Virtual bases? 19306c3fb27SDimitry Andric const CXXMethodDecl * 19406c3fb27SDimitry Andric Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, 19506c3fb27SDimitry Andric const CXXRecordDecl *StaticDecl, 19606c3fb27SDimitry Andric const CXXMethodDecl *InitialFunction) const { 19706c3fb27SDimitry Andric 19806c3fb27SDimitry Andric const CXXRecordDecl *CurRecord = DynamicDecl; 19906c3fb27SDimitry Andric const CXXMethodDecl *FoundFunction = InitialFunction; 20006c3fb27SDimitry Andric for (;;) { 20106c3fb27SDimitry Andric const CXXMethodDecl *Overrider = 20206c3fb27SDimitry Andric FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); 20306c3fb27SDimitry Andric if (Overrider) 20406c3fb27SDimitry Andric return Overrider; 20506c3fb27SDimitry Andric 20606c3fb27SDimitry Andric // Common case of only one base class. 20706c3fb27SDimitry Andric if (CurRecord->getNumBases() == 1) { 20806c3fb27SDimitry Andric CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); 20906c3fb27SDimitry Andric continue; 21006c3fb27SDimitry Andric } 21106c3fb27SDimitry Andric 21206c3fb27SDimitry Andric // Otherwise, go to the base class that will lead to the StaticDecl. 21306c3fb27SDimitry Andric for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { 21406c3fb27SDimitry Andric const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); 21506c3fb27SDimitry Andric if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { 21606c3fb27SDimitry Andric CurRecord = Base; 21706c3fb27SDimitry Andric break; 21806c3fb27SDimitry Andric } 21906c3fb27SDimitry Andric } 22006c3fb27SDimitry Andric } 22106c3fb27SDimitry Andric 22206c3fb27SDimitry Andric llvm_unreachable( 22306c3fb27SDimitry Andric "Couldn't find an overriding function in the class hierarchy?"); 22406c3fb27SDimitry Andric return nullptr; 22506c3fb27SDimitry Andric } 226*5f757f3fSDimitry Andric 227*5f757f3fSDimitry Andric const Function *Context::getOrCreateFunction(const FunctionDecl *FD) { 228*5f757f3fSDimitry Andric assert(FD); 229*5f757f3fSDimitry Andric const Function *Func = P->getFunction(FD); 230*5f757f3fSDimitry Andric bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled(); 231*5f757f3fSDimitry Andric bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined(); 232*5f757f3fSDimitry Andric 233*5f757f3fSDimitry Andric if (IsBeingCompiled) 234*5f757f3fSDimitry Andric return Func; 235*5f757f3fSDimitry Andric 236*5f757f3fSDimitry Andric if (!Func || WasNotDefined) { 237*5f757f3fSDimitry Andric if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) 238*5f757f3fSDimitry Andric Func = *R; 239*5f757f3fSDimitry Andric else { 240*5f757f3fSDimitry Andric llvm::consumeError(R.takeError()); 241*5f757f3fSDimitry Andric return nullptr; 242*5f757f3fSDimitry Andric } 243*5f757f3fSDimitry Andric } 244*5f757f3fSDimitry Andric 245*5f757f3fSDimitry Andric return Func; 246*5f757f3fSDimitry Andric } 247