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" 12a7dea167SDimitry Andric #include "ByteCodeStmtGen.h" 13a7dea167SDimitry Andric #include "EvalEmitter.h" 14a7dea167SDimitry Andric #include "Interp.h" 15a7dea167SDimitry Andric #include "InterpFrame.h" 16a7dea167SDimitry Andric #include "InterpStack.h" 17a7dea167SDimitry Andric #include "PrimType.h" 18a7dea167SDimitry Andric #include "Program.h" 19a7dea167SDimitry Andric #include "clang/AST/Expr.h" 205ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h" 21a7dea167SDimitry Andric 22a7dea167SDimitry Andric using namespace clang; 23a7dea167SDimitry Andric using namespace clang::interp; 24a7dea167SDimitry Andric 25480093f4SDimitry Andric Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 26a7dea167SDimitry Andric 27a7dea167SDimitry Andric Context::~Context() {} 28a7dea167SDimitry Andric 29480093f4SDimitry Andric bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 30*bdd1243dSDimitry Andric assert(Stk.empty()); 31a7dea167SDimitry Andric Function *Func = P->getFunction(FD); 32*bdd1243dSDimitry Andric if (!Func || !Func->hasBody()) { 33a7dea167SDimitry Andric if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) { 34a7dea167SDimitry Andric Func = *R; 35480093f4SDimitry Andric } else { 36a7dea167SDimitry Andric handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) { 37*bdd1243dSDimitry Andric Parent.FFDiag(Err.getRange().getBegin(), 38*bdd1243dSDimitry Andric diag::err_experimental_clang_interp_failed) 39*bdd1243dSDimitry Andric << Err.getRange(); 40a7dea167SDimitry Andric }); 41480093f4SDimitry Andric return false; 42a7dea167SDimitry Andric } 43a7dea167SDimitry Andric } 44a7dea167SDimitry Andric 45*bdd1243dSDimitry Andric return Func->isConstexpr(); 46a7dea167SDimitry Andric } 47a7dea167SDimitry Andric 48480093f4SDimitry Andric bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 49*bdd1243dSDimitry Andric assert(Stk.empty()); 50a7dea167SDimitry Andric ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 51*bdd1243dSDimitry Andric if (Check(Parent, C.interpretExpr(E))) { 52*bdd1243dSDimitry Andric assert(Stk.empty()); 53*bdd1243dSDimitry Andric return true; 54*bdd1243dSDimitry Andric } 55*bdd1243dSDimitry Andric 56*bdd1243dSDimitry Andric Stk.clear(); 57*bdd1243dSDimitry Andric return false; 58a7dea167SDimitry Andric } 59a7dea167SDimitry Andric 60480093f4SDimitry Andric bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 61a7dea167SDimitry Andric APValue &Result) { 62*bdd1243dSDimitry Andric assert(Stk.empty()); 63a7dea167SDimitry Andric ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 64*bdd1243dSDimitry Andric if (Check(Parent, C.interpretDecl(VD))) { 65*bdd1243dSDimitry Andric assert(Stk.empty()); 66*bdd1243dSDimitry Andric return true; 67*bdd1243dSDimitry Andric } 68*bdd1243dSDimitry Andric 69*bdd1243dSDimitry Andric Stk.clear(); 70*bdd1243dSDimitry Andric return false; 71a7dea167SDimitry Andric } 72a7dea167SDimitry Andric 73a7dea167SDimitry Andric const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 74a7dea167SDimitry Andric 75*bdd1243dSDimitry Andric std::optional<PrimType> Context::classify(QualType T) const { 76a7dea167SDimitry Andric if (T->isReferenceType() || T->isPointerType()) { 77a7dea167SDimitry Andric return PT_Ptr; 78a7dea167SDimitry Andric } 79a7dea167SDimitry Andric 80a7dea167SDimitry Andric if (T->isBooleanType()) 81a7dea167SDimitry Andric return PT_Bool; 82a7dea167SDimitry Andric 83a7dea167SDimitry Andric if (T->isSignedIntegerOrEnumerationType()) { 84a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 85a7dea167SDimitry Andric case 64: 86a7dea167SDimitry Andric return PT_Sint64; 87a7dea167SDimitry Andric case 32: 88a7dea167SDimitry Andric return PT_Sint32; 89a7dea167SDimitry Andric case 16: 90a7dea167SDimitry Andric return PT_Sint16; 91a7dea167SDimitry Andric case 8: 92a7dea167SDimitry Andric return PT_Sint8; 93a7dea167SDimitry Andric default: 94a7dea167SDimitry Andric return {}; 95a7dea167SDimitry Andric } 96a7dea167SDimitry Andric } 97a7dea167SDimitry Andric 98a7dea167SDimitry Andric if (T->isUnsignedIntegerOrEnumerationType()) { 99a7dea167SDimitry Andric switch (Ctx.getIntWidth(T)) { 100a7dea167SDimitry Andric case 64: 101a7dea167SDimitry Andric return PT_Uint64; 102a7dea167SDimitry Andric case 32: 103a7dea167SDimitry Andric return PT_Uint32; 104a7dea167SDimitry Andric case 16: 105a7dea167SDimitry Andric return PT_Uint16; 106a7dea167SDimitry Andric case 8: 107a7dea167SDimitry Andric return PT_Uint8; 108a7dea167SDimitry Andric default: 109a7dea167SDimitry Andric return {}; 110a7dea167SDimitry Andric } 111a7dea167SDimitry Andric } 112a7dea167SDimitry Andric 113a7dea167SDimitry Andric if (T->isNullPtrType()) 114a7dea167SDimitry Andric return PT_Ptr; 115a7dea167SDimitry Andric 116a7dea167SDimitry Andric if (auto *AT = dyn_cast<AtomicType>(T)) 117a7dea167SDimitry Andric return classify(AT->getValueType()); 118a7dea167SDimitry Andric 119a7dea167SDimitry Andric return {}; 120a7dea167SDimitry Andric } 121a7dea167SDimitry Andric 122a7dea167SDimitry Andric unsigned Context::getCharBit() const { 123a7dea167SDimitry Andric return Ctx.getTargetInfo().getCharWidth(); 124a7dea167SDimitry Andric } 125a7dea167SDimitry Andric 126480093f4SDimitry Andric bool Context::Run(State &Parent, Function *Func, APValue &Result) { 127a7dea167SDimitry Andric InterpState State(Parent, *P, Stk, *this); 128*bdd1243dSDimitry Andric State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {}); 129480093f4SDimitry Andric if (Interpret(State, Result)) 130480093f4SDimitry Andric return true; 131a7dea167SDimitry Andric Stk.clear(); 132480093f4SDimitry Andric return false; 133a7dea167SDimitry Andric } 134a7dea167SDimitry Andric 135480093f4SDimitry Andric bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) { 136480093f4SDimitry Andric if (Flag) 137480093f4SDimitry Andric return *Flag; 138480093f4SDimitry Andric handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) { 139*bdd1243dSDimitry Andric Parent.FFDiag(Err.getRange().getBegin(), 140*bdd1243dSDimitry Andric diag::err_experimental_clang_interp_failed) 141*bdd1243dSDimitry Andric << Err.getRange(); 142a7dea167SDimitry Andric }); 143480093f4SDimitry Andric return false; 144a7dea167SDimitry Andric } 145