1e5dd7070Spatrick //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick
9e5dd7070Spatrick #include "Context.h"
10e5dd7070Spatrick #include "ByteCodeEmitter.h"
11e5dd7070Spatrick #include "ByteCodeExprGen.h"
12e5dd7070Spatrick #include "ByteCodeStmtGen.h"
13e5dd7070Spatrick #include "EvalEmitter.h"
14e5dd7070Spatrick #include "Interp.h"
15e5dd7070Spatrick #include "InterpFrame.h"
16e5dd7070Spatrick #include "InterpStack.h"
17e5dd7070Spatrick #include "PrimType.h"
18e5dd7070Spatrick #include "Program.h"
19e5dd7070Spatrick #include "clang/AST/Expr.h"
20ec727ea7Spatrick #include "clang/Basic/TargetInfo.h"
21e5dd7070Spatrick
22e5dd7070Spatrick using namespace clang;
23e5dd7070Spatrick using namespace clang::interp;
24e5dd7070Spatrick
Context(ASTContext & Ctx)25e5dd7070Spatrick Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {}
26e5dd7070Spatrick
~Context()27e5dd7070Spatrick Context::~Context() {}
28e5dd7070Spatrick
isPotentialConstantExpr(State & Parent,const FunctionDecl * FD)29e5dd7070Spatrick bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
30*12c85518Srobert assert(Stk.empty());
31e5dd7070Spatrick Function *Func = P->getFunction(FD);
32*12c85518Srobert if (!Func || !Func->hasBody()) {
33e5dd7070Spatrick if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) {
34e5dd7070Spatrick Func = *R;
35e5dd7070Spatrick } else {
36e5dd7070Spatrick handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) {
37*12c85518Srobert Parent.FFDiag(Err.getRange().getBegin(),
38*12c85518Srobert diag::err_experimental_clang_interp_failed)
39*12c85518Srobert << Err.getRange();
40e5dd7070Spatrick });
41e5dd7070Spatrick return false;
42e5dd7070Spatrick }
43e5dd7070Spatrick }
44e5dd7070Spatrick
45*12c85518Srobert return Func->isConstexpr();
46e5dd7070Spatrick }
47e5dd7070Spatrick
evaluateAsRValue(State & Parent,const Expr * E,APValue & Result)48e5dd7070Spatrick bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
49*12c85518Srobert assert(Stk.empty());
50e5dd7070Spatrick ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
51*12c85518Srobert if (Check(Parent, C.interpretExpr(E))) {
52*12c85518Srobert assert(Stk.empty());
53*12c85518Srobert return true;
54*12c85518Srobert }
55*12c85518Srobert
56*12c85518Srobert Stk.clear();
57*12c85518Srobert return false;
58e5dd7070Spatrick }
59e5dd7070Spatrick
evaluateAsInitializer(State & Parent,const VarDecl * VD,APValue & Result)60e5dd7070Spatrick bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
61e5dd7070Spatrick APValue &Result) {
62*12c85518Srobert assert(Stk.empty());
63e5dd7070Spatrick ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
64*12c85518Srobert if (Check(Parent, C.interpretDecl(VD))) {
65*12c85518Srobert assert(Stk.empty());
66*12c85518Srobert return true;
67*12c85518Srobert }
68*12c85518Srobert
69*12c85518Srobert Stk.clear();
70*12c85518Srobert return false;
71e5dd7070Spatrick }
72e5dd7070Spatrick
getLangOpts() const73e5dd7070Spatrick const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
74e5dd7070Spatrick
classify(QualType T) const75*12c85518Srobert std::optional<PrimType> Context::classify(QualType T) const {
76e5dd7070Spatrick if (T->isReferenceType() || T->isPointerType()) {
77e5dd7070Spatrick return PT_Ptr;
78e5dd7070Spatrick }
79e5dd7070Spatrick
80e5dd7070Spatrick if (T->isBooleanType())
81e5dd7070Spatrick return PT_Bool;
82e5dd7070Spatrick
83e5dd7070Spatrick if (T->isSignedIntegerOrEnumerationType()) {
84e5dd7070Spatrick switch (Ctx.getIntWidth(T)) {
85e5dd7070Spatrick case 64:
86e5dd7070Spatrick return PT_Sint64;
87e5dd7070Spatrick case 32:
88e5dd7070Spatrick return PT_Sint32;
89e5dd7070Spatrick case 16:
90e5dd7070Spatrick return PT_Sint16;
91e5dd7070Spatrick case 8:
92e5dd7070Spatrick return PT_Sint8;
93e5dd7070Spatrick default:
94e5dd7070Spatrick return {};
95e5dd7070Spatrick }
96e5dd7070Spatrick }
97e5dd7070Spatrick
98e5dd7070Spatrick if (T->isUnsignedIntegerOrEnumerationType()) {
99e5dd7070Spatrick switch (Ctx.getIntWidth(T)) {
100e5dd7070Spatrick case 64:
101e5dd7070Spatrick return PT_Uint64;
102e5dd7070Spatrick case 32:
103e5dd7070Spatrick return PT_Uint32;
104e5dd7070Spatrick case 16:
105e5dd7070Spatrick return PT_Uint16;
106e5dd7070Spatrick case 8:
107e5dd7070Spatrick return PT_Uint8;
108e5dd7070Spatrick default:
109e5dd7070Spatrick return {};
110e5dd7070Spatrick }
111e5dd7070Spatrick }
112e5dd7070Spatrick
113e5dd7070Spatrick if (T->isNullPtrType())
114e5dd7070Spatrick return PT_Ptr;
115e5dd7070Spatrick
116e5dd7070Spatrick if (auto *AT = dyn_cast<AtomicType>(T))
117e5dd7070Spatrick return classify(AT->getValueType());
118e5dd7070Spatrick
119e5dd7070Spatrick return {};
120e5dd7070Spatrick }
121e5dd7070Spatrick
getCharBit() const122e5dd7070Spatrick unsigned Context::getCharBit() const {
123e5dd7070Spatrick return Ctx.getTargetInfo().getCharWidth();
124e5dd7070Spatrick }
125e5dd7070Spatrick
Run(State & Parent,Function * Func,APValue & Result)126e5dd7070Spatrick bool Context::Run(State &Parent, Function *Func, APValue &Result) {
127e5dd7070Spatrick InterpState State(Parent, *P, Stk, *this);
128*12c85518Srobert State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {});
129e5dd7070Spatrick if (Interpret(State, Result))
130e5dd7070Spatrick return true;
131e5dd7070Spatrick Stk.clear();
132e5dd7070Spatrick return false;
133e5dd7070Spatrick }
134e5dd7070Spatrick
Check(State & Parent,llvm::Expected<bool> && Flag)135e5dd7070Spatrick bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) {
136e5dd7070Spatrick if (Flag)
137e5dd7070Spatrick return *Flag;
138e5dd7070Spatrick handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
139*12c85518Srobert Parent.FFDiag(Err.getRange().getBegin(),
140*12c85518Srobert diag::err_experimental_clang_interp_failed)
141*12c85518Srobert << Err.getRange();
142e5dd7070Spatrick });
143e5dd7070Spatrick return false;
144e5dd7070Spatrick }
145