1 //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "ByteCodeEmitter.h"
11 #include "ByteCodeExprGen.h"
12 #include "ByteCodeGenError.h"
13 #include "ByteCodeStmtGen.h"
14 #include "EvalEmitter.h"
16 #include "InterpFrame.h"
17 #include "InterpStack.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/Basic/TargetInfo.h"
23 using namespace clang
;
24 using namespace clang::interp
;
26 Context::Context(ASTContext
&Ctx
) : Ctx(Ctx
), P(new Program(*this)) {}
28 Context::~Context() {}
30 bool Context::isPotentialConstantExpr(State
&Parent
, const FunctionDecl
*FD
) {
32 Function
*Func
= P
->getFunction(FD
);
33 if (!Func
|| !Func
->hasBody()) {
34 if (auto R
= ByteCodeStmtGen
<ByteCodeEmitter
>(*this, *P
).compileFunc(FD
)) {
37 handleAllErrors(R
.takeError(), [&Parent
](ByteCodeGenError
&Err
) {
38 Parent
.FFDiag(Err
.getRange().getBegin(),
39 diag::err_experimental_clang_interp_failed
)
47 if (!Run(Parent
, Func
, DummyResult
)) {
51 return Func
->isConstexpr();
54 bool Context::evaluateAsRValue(State
&Parent
, const Expr
*E
, APValue
&Result
) {
56 ByteCodeExprGen
<EvalEmitter
> C(*this, *P
, Parent
, Stk
, Result
);
57 if (Check(Parent
, C
.interpretExpr(E
))) {
60 // Make sure we don't rely on some value being still alive in
61 // InterpStack memory.
71 bool Context::evaluateAsInitializer(State
&Parent
, const VarDecl
*VD
,
74 ByteCodeExprGen
<EvalEmitter
> C(*this, *P
, Parent
, Stk
, Result
);
75 if (Check(Parent
, C
.interpretDecl(VD
))) {
78 // Make sure we don't rely on some value being still alive in
79 // InterpStack memory.
89 const LangOptions
&Context::getLangOpts() const { return Ctx
.getLangOpts(); }
91 std::optional
<PrimType
> Context::classify(QualType T
) const {
92 if (T
->isBooleanType())
95 if (T
->isSignedIntegerOrEnumerationType()) {
96 switch (Ctx
.getIntWidth(T
)) {
110 if (T
->isUnsignedIntegerOrEnumerationType()) {
111 switch (Ctx
.getIntWidth(T
)) {
125 if (T
->isNullPtrType())
128 if (T
->isFloatingType())
131 if (T
->isFunctionPointerType() || T
->isFunctionReferenceType() ||
132 T
->isFunctionType() || T
->isSpecificBuiltinType(BuiltinType::BoundMember
))
135 if (T
->isReferenceType() || T
->isPointerType())
138 if (const auto *AT
= dyn_cast
<AtomicType
>(T
))
139 return classify(AT
->getValueType());
141 if (const auto *DT
= dyn_cast
<DecltypeType
>(T
))
142 return classify(DT
->getUnderlyingType());
144 if (const auto *DT
= dyn_cast
<MemberPointerType
>(T
))
145 return classify(DT
->getPointeeType());
150 unsigned Context::getCharBit() const {
151 return Ctx
.getTargetInfo().getCharWidth();
154 /// Simple wrapper around getFloatTypeSemantics() to make code a
156 const llvm::fltSemantics
&Context::getFloatSemantics(QualType T
) const {
157 return Ctx
.getFloatTypeSemantics(T
);
160 bool Context::Run(State
&Parent
, const Function
*Func
, APValue
&Result
) {
163 InterpState
State(Parent
, *P
, Stk
, *this);
164 State
.Current
= new InterpFrame(State
, Func
, /*Caller=*/nullptr, {});
165 if (Interpret(State
, Result
)) {
170 // State gets destroyed here, so the Stk.clear() below doesn't accidentally
171 // remove values the State's destructor might accedd.
178 bool Context::Check(State
&Parent
, llvm::Expected
<bool> &&Flag
) {
181 handleAllErrors(Flag
.takeError(), [&Parent
](ByteCodeGenError
&Err
) {
182 Parent
.FFDiag(Err
.getRange().getBegin(),
183 diag::err_experimental_clang_interp_failed
)
189 // TODO: Virtual bases?
190 const CXXMethodDecl
*
191 Context::getOverridingFunction(const CXXRecordDecl
*DynamicDecl
,
192 const CXXRecordDecl
*StaticDecl
,
193 const CXXMethodDecl
*InitialFunction
) const {
195 const CXXRecordDecl
*CurRecord
= DynamicDecl
;
196 const CXXMethodDecl
*FoundFunction
= InitialFunction
;
198 const CXXMethodDecl
*Overrider
=
199 FoundFunction
->getCorrespondingMethodDeclaredInClass(CurRecord
, false);
203 // Common case of only one base class.
204 if (CurRecord
->getNumBases() == 1) {
205 CurRecord
= CurRecord
->bases_begin()->getType()->getAsCXXRecordDecl();
209 // Otherwise, go to the base class that will lead to the StaticDecl.
210 for (const CXXBaseSpecifier
&Spec
: CurRecord
->bases()) {
211 const CXXRecordDecl
*Base
= Spec
.getType()->getAsCXXRecordDecl();
212 if (Base
== StaticDecl
|| Base
->isDerivedFrom(StaticDecl
)) {
220 "Couldn't find an overriding function in the class hierarchy?");
224 const Function
*Context::getOrCreateFunction(const FunctionDecl
*FD
) {
226 const Function
*Func
= P
->getFunction(FD
);
227 bool IsBeingCompiled
= Func
&& Func
->isDefined() && !Func
->isFullyCompiled();
228 bool WasNotDefined
= Func
&& !Func
->isConstexpr() && !Func
->isDefined();
233 if (!Func
|| WasNotDefined
) {
234 if (auto R
= ByteCodeStmtGen
<ByteCodeEmitter
>(*this, *P
).compileFunc(FD
))
237 llvm::consumeError(R
.takeError());