xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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"
125f757f3fSDimitry 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);
33*7a6dacacSDimitry Andric   if (!Func || !Func->hasBody())
34*7a6dacacSDimitry Andric     Func = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
35a7dea167SDimitry Andric 
3606c3fb27SDimitry Andric   APValue DummyResult;
3706c3fb27SDimitry Andric   if (!Run(Parent, Func, DummyResult)) {
3806c3fb27SDimitry Andric     return false;
3906c3fb27SDimitry Andric   }
4006c3fb27SDimitry Andric 
41bdd1243dSDimitry Andric   return Func->isConstexpr();
42a7dea167SDimitry Andric }
43a7dea167SDimitry Andric 
44480093f4SDimitry Andric bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
45bdd1243dSDimitry Andric   assert(Stk.empty());
46a7dea167SDimitry Andric   ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
47*7a6dacacSDimitry Andric 
48*7a6dacacSDimitry Andric   auto Res = C.interpretExpr(E);
49*7a6dacacSDimitry Andric 
50*7a6dacacSDimitry Andric   if (Res.isInvalid()) {
51*7a6dacacSDimitry Andric     Stk.clear();
52*7a6dacacSDimitry Andric     return false;
53*7a6dacacSDimitry Andric   }
54*7a6dacacSDimitry Andric 
55bdd1243dSDimitry Andric   assert(Stk.empty());
5606c3fb27SDimitry Andric #ifndef NDEBUG
5706c3fb27SDimitry Andric   // Make sure we don't rely on some value being still alive in
5806c3fb27SDimitry Andric   // InterpStack memory.
5906c3fb27SDimitry Andric   Stk.clear();
6006c3fb27SDimitry Andric #endif
61*7a6dacacSDimitry Andric 
62*7a6dacacSDimitry Andric   // Implicit lvalue-to-rvalue conversion.
63*7a6dacacSDimitry Andric   if (E->isGLValue()) {
64*7a6dacacSDimitry Andric     std::optional<APValue> RValueResult = Res.toRValue();
65*7a6dacacSDimitry Andric     if (!RValueResult) {
66*7a6dacacSDimitry Andric       return false;
67*7a6dacacSDimitry Andric     }
68*7a6dacacSDimitry Andric     Result = *RValueResult;
69*7a6dacacSDimitry Andric   } else {
70*7a6dacacSDimitry Andric     Result = Res.toAPValue();
71*7a6dacacSDimitry Andric   }
72*7a6dacacSDimitry Andric 
73bdd1243dSDimitry Andric   return true;
74bdd1243dSDimitry Andric }
75bdd1243dSDimitry Andric 
76*7a6dacacSDimitry Andric bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
77*7a6dacacSDimitry Andric   assert(Stk.empty());
78*7a6dacacSDimitry Andric   ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
79*7a6dacacSDimitry Andric 
80*7a6dacacSDimitry Andric   auto Res = C.interpretExpr(E);
81*7a6dacacSDimitry Andric   if (Res.isInvalid()) {
82bdd1243dSDimitry Andric     Stk.clear();
83bdd1243dSDimitry Andric     return false;
84a7dea167SDimitry Andric   }
85a7dea167SDimitry Andric 
86*7a6dacacSDimitry Andric   assert(Stk.empty());
87*7a6dacacSDimitry Andric #ifndef NDEBUG
88*7a6dacacSDimitry Andric   // Make sure we don't rely on some value being still alive in
89*7a6dacacSDimitry Andric   // InterpStack memory.
90*7a6dacacSDimitry Andric   Stk.clear();
91*7a6dacacSDimitry Andric #endif
92*7a6dacacSDimitry Andric   Result = Res.toAPValue();
93*7a6dacacSDimitry Andric   return true;
94*7a6dacacSDimitry Andric }
95*7a6dacacSDimitry Andric 
96480093f4SDimitry Andric bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
97a7dea167SDimitry Andric                                     APValue &Result) {
98bdd1243dSDimitry Andric   assert(Stk.empty());
99a7dea167SDimitry Andric   ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
100*7a6dacacSDimitry Andric 
101*7a6dacacSDimitry Andric   auto Res = C.interpretDecl(VD);
102*7a6dacacSDimitry Andric   if (Res.isInvalid()) {
103*7a6dacacSDimitry Andric     Stk.clear();
104*7a6dacacSDimitry Andric     return false;
105*7a6dacacSDimitry Andric   }
106*7a6dacacSDimitry Andric 
107bdd1243dSDimitry Andric   assert(Stk.empty());
10806c3fb27SDimitry Andric #ifndef NDEBUG
10906c3fb27SDimitry Andric   // Make sure we don't rely on some value being still alive in
11006c3fb27SDimitry Andric   // InterpStack memory.
11106c3fb27SDimitry Andric   Stk.clear();
11206c3fb27SDimitry Andric #endif
113bdd1243dSDimitry Andric 
114*7a6dacacSDimitry Andric   // Ensure global variables are fully initialized.
115*7a6dacacSDimitry Andric   if (shouldBeGloballyIndexed(VD) && !Res.isInvalid() &&
116*7a6dacacSDimitry Andric       (VD->getType()->isRecordType() || VD->getType()->isArrayType())) {
117*7a6dacacSDimitry Andric     assert(Res.isLValue());
118*7a6dacacSDimitry Andric 
119*7a6dacacSDimitry Andric     if (!Res.checkFullyInitialized(C.getState()))
120bdd1243dSDimitry Andric       return false;
121*7a6dacacSDimitry Andric 
122*7a6dacacSDimitry Andric     // lvalue-to-rvalue conversion.
123*7a6dacacSDimitry Andric     std::optional<APValue> RValueResult = Res.toRValue();
124*7a6dacacSDimitry Andric     if (!RValueResult)
125*7a6dacacSDimitry Andric       return false;
126*7a6dacacSDimitry Andric     Result = *RValueResult;
127*7a6dacacSDimitry Andric 
128*7a6dacacSDimitry Andric   } else
129*7a6dacacSDimitry Andric     Result = Res.toAPValue();
130*7a6dacacSDimitry Andric   return true;
131a7dea167SDimitry Andric }
132a7dea167SDimitry Andric 
133a7dea167SDimitry Andric const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
134a7dea167SDimitry Andric 
135bdd1243dSDimitry Andric std::optional<PrimType> Context::classify(QualType T) const {
136a7dea167SDimitry Andric   if (T->isBooleanType())
137a7dea167SDimitry Andric     return PT_Bool;
138a7dea167SDimitry Andric 
1395f757f3fSDimitry Andric   if (T->isAnyComplexType())
1405f757f3fSDimitry Andric     return std::nullopt;
1415f757f3fSDimitry Andric 
142a7dea167SDimitry Andric   if (T->isSignedIntegerOrEnumerationType()) {
143a7dea167SDimitry Andric     switch (Ctx.getIntWidth(T)) {
144a7dea167SDimitry Andric     case 64:
145a7dea167SDimitry Andric       return PT_Sint64;
146a7dea167SDimitry Andric     case 32:
147a7dea167SDimitry Andric       return PT_Sint32;
148a7dea167SDimitry Andric     case 16:
149a7dea167SDimitry Andric       return PT_Sint16;
150a7dea167SDimitry Andric     case 8:
151a7dea167SDimitry Andric       return PT_Sint8;
152a7dea167SDimitry Andric     default:
1535f757f3fSDimitry Andric       return PT_IntAPS;
154a7dea167SDimitry Andric     }
155a7dea167SDimitry Andric   }
156a7dea167SDimitry Andric 
157a7dea167SDimitry Andric   if (T->isUnsignedIntegerOrEnumerationType()) {
158a7dea167SDimitry Andric     switch (Ctx.getIntWidth(T)) {
159a7dea167SDimitry Andric     case 64:
160a7dea167SDimitry Andric       return PT_Uint64;
161a7dea167SDimitry Andric     case 32:
162a7dea167SDimitry Andric       return PT_Uint32;
163a7dea167SDimitry Andric     case 16:
164a7dea167SDimitry Andric       return PT_Uint16;
165a7dea167SDimitry Andric     case 8:
166a7dea167SDimitry Andric       return PT_Uint8;
167a7dea167SDimitry Andric     default:
1685f757f3fSDimitry Andric       return PT_IntAP;
169a7dea167SDimitry Andric     }
170a7dea167SDimitry Andric   }
171a7dea167SDimitry Andric 
172a7dea167SDimitry Andric   if (T->isNullPtrType())
173a7dea167SDimitry Andric     return PT_Ptr;
174a7dea167SDimitry Andric 
17506c3fb27SDimitry Andric   if (T->isFloatingType())
17606c3fb27SDimitry Andric     return PT_Float;
17706c3fb27SDimitry Andric 
1785f757f3fSDimitry Andric   if (T->isFunctionPointerType() || T->isFunctionReferenceType() ||
1795f757f3fSDimitry Andric       T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember))
1805f757f3fSDimitry Andric     return PT_FnPtr;
1815f757f3fSDimitry Andric 
1825f757f3fSDimitry Andric   if (T->isReferenceType() || T->isPointerType())
1835f757f3fSDimitry Andric     return PT_Ptr;
1845f757f3fSDimitry Andric 
1855f757f3fSDimitry Andric   if (const auto *AT = dyn_cast<AtomicType>(T))
186a7dea167SDimitry Andric     return classify(AT->getValueType());
187a7dea167SDimitry Andric 
1885f757f3fSDimitry Andric   if (const auto *DT = dyn_cast<DecltypeType>(T))
1895f757f3fSDimitry Andric     return classify(DT->getUnderlyingType());
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric   if (const auto *DT = dyn_cast<MemberPointerType>(T))
1925f757f3fSDimitry Andric     return classify(DT->getPointeeType());
1935f757f3fSDimitry Andric 
1945f757f3fSDimitry Andric   return std::nullopt;
195a7dea167SDimitry Andric }
196a7dea167SDimitry Andric 
197a7dea167SDimitry Andric unsigned Context::getCharBit() const {
198a7dea167SDimitry Andric   return Ctx.getTargetInfo().getCharWidth();
199a7dea167SDimitry Andric }
200a7dea167SDimitry Andric 
20106c3fb27SDimitry Andric /// Simple wrapper around getFloatTypeSemantics() to make code a
20206c3fb27SDimitry Andric /// little shorter.
20306c3fb27SDimitry Andric const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
20406c3fb27SDimitry Andric   return Ctx.getFloatTypeSemantics(T);
20506c3fb27SDimitry Andric }
20606c3fb27SDimitry Andric 
20706c3fb27SDimitry Andric bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
2085f757f3fSDimitry Andric 
2095f757f3fSDimitry Andric   {
210a7dea167SDimitry Andric     InterpState State(Parent, *P, Stk, *this);
211bdd1243dSDimitry Andric     State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {});
2125f757f3fSDimitry Andric     if (Interpret(State, Result)) {
2135f757f3fSDimitry Andric       assert(Stk.empty());
214480093f4SDimitry Andric       return true;
2155f757f3fSDimitry Andric     }
2165f757f3fSDimitry Andric 
2175f757f3fSDimitry Andric     // State gets destroyed here, so the Stk.clear() below doesn't accidentally
2185f757f3fSDimitry Andric     // remove values the State's destructor might access.
2195f757f3fSDimitry Andric   }
2205f757f3fSDimitry Andric 
221a7dea167SDimitry Andric   Stk.clear();
222480093f4SDimitry Andric   return false;
223a7dea167SDimitry Andric }
224a7dea167SDimitry Andric 
225480093f4SDimitry Andric bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) {
226480093f4SDimitry Andric   if (Flag)
227480093f4SDimitry Andric     return *Flag;
228480093f4SDimitry Andric   handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
229bdd1243dSDimitry Andric     Parent.FFDiag(Err.getRange().getBegin(),
230bdd1243dSDimitry Andric                   diag::err_experimental_clang_interp_failed)
231bdd1243dSDimitry Andric         << Err.getRange();
232a7dea167SDimitry Andric   });
233480093f4SDimitry Andric   return false;
234a7dea167SDimitry Andric }
23506c3fb27SDimitry Andric 
23606c3fb27SDimitry Andric // TODO: Virtual bases?
23706c3fb27SDimitry Andric const CXXMethodDecl *
23806c3fb27SDimitry Andric Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
23906c3fb27SDimitry Andric                                const CXXRecordDecl *StaticDecl,
24006c3fb27SDimitry Andric                                const CXXMethodDecl *InitialFunction) const {
24106c3fb27SDimitry Andric 
24206c3fb27SDimitry Andric   const CXXRecordDecl *CurRecord = DynamicDecl;
24306c3fb27SDimitry Andric   const CXXMethodDecl *FoundFunction = InitialFunction;
24406c3fb27SDimitry Andric   for (;;) {
24506c3fb27SDimitry Andric     const CXXMethodDecl *Overrider =
24606c3fb27SDimitry Andric         FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
24706c3fb27SDimitry Andric     if (Overrider)
24806c3fb27SDimitry Andric       return Overrider;
24906c3fb27SDimitry Andric 
25006c3fb27SDimitry Andric     // Common case of only one base class.
25106c3fb27SDimitry Andric     if (CurRecord->getNumBases() == 1) {
25206c3fb27SDimitry Andric       CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
25306c3fb27SDimitry Andric       continue;
25406c3fb27SDimitry Andric     }
25506c3fb27SDimitry Andric 
25606c3fb27SDimitry Andric     // Otherwise, go to the base class that will lead to the StaticDecl.
25706c3fb27SDimitry Andric     for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
25806c3fb27SDimitry Andric       const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
25906c3fb27SDimitry Andric       if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
26006c3fb27SDimitry Andric         CurRecord = Base;
26106c3fb27SDimitry Andric         break;
26206c3fb27SDimitry Andric       }
26306c3fb27SDimitry Andric     }
26406c3fb27SDimitry Andric   }
26506c3fb27SDimitry Andric 
26606c3fb27SDimitry Andric   llvm_unreachable(
26706c3fb27SDimitry Andric       "Couldn't find an overriding function in the class hierarchy?");
26806c3fb27SDimitry Andric   return nullptr;
26906c3fb27SDimitry Andric }
2705f757f3fSDimitry Andric 
2715f757f3fSDimitry Andric const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
2725f757f3fSDimitry Andric   assert(FD);
2735f757f3fSDimitry Andric   const Function *Func = P->getFunction(FD);
2745f757f3fSDimitry Andric   bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled();
2755f757f3fSDimitry Andric   bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined();
2765f757f3fSDimitry Andric 
2775f757f3fSDimitry Andric   if (IsBeingCompiled)
2785f757f3fSDimitry Andric     return Func;
2795f757f3fSDimitry Andric 
2805f757f3fSDimitry Andric   if (!Func || WasNotDefined) {
281*7a6dacacSDimitry Andric     if (auto F = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
282*7a6dacacSDimitry Andric       Func = F;
2835f757f3fSDimitry Andric   }
2845f757f3fSDimitry Andric 
2855f757f3fSDimitry Andric   return Func;
2865f757f3fSDimitry Andric }
287