xref: /llvm-project/clang/lib/AST/ByteCode/Context.h (revision 82ed9c0319c9f0373bcb633a03ce6d35ebac3661)
1a07aba5dSTimm Baeder //===--- Context.h - Context for the constexpr VM ---------------*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder //
9a07aba5dSTimm Baeder // Defines the constexpr execution context.
10a07aba5dSTimm Baeder //
11a07aba5dSTimm Baeder // The execution context manages cached bytecode and the global context.
12a07aba5dSTimm Baeder // It invokes the compiler and interpreter, propagating errors.
13a07aba5dSTimm Baeder //
14a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
15a07aba5dSTimm Baeder 
16a07aba5dSTimm Baeder #ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H
17a07aba5dSTimm Baeder #define LLVM_CLANG_AST_INTERP_CONTEXT_H
18a07aba5dSTimm Baeder 
19a07aba5dSTimm Baeder #include "InterpStack.h"
20a07aba5dSTimm Baeder 
21a07aba5dSTimm Baeder namespace clang {
22a07aba5dSTimm Baeder class ASTContext;
23a07aba5dSTimm Baeder class LangOptions;
24a07aba5dSTimm Baeder class FunctionDecl;
25a07aba5dSTimm Baeder class VarDecl;
26a07aba5dSTimm Baeder class APValue;
27a07aba5dSTimm Baeder 
28a07aba5dSTimm Baeder namespace interp {
29a07aba5dSTimm Baeder class Function;
30a07aba5dSTimm Baeder class Program;
31a07aba5dSTimm Baeder class State;
32a07aba5dSTimm Baeder enum PrimType : unsigned;
33a07aba5dSTimm Baeder 
34a07aba5dSTimm Baeder struct ParamOffset {
35a07aba5dSTimm Baeder   unsigned Offset;
36a07aba5dSTimm Baeder   bool IsPtr;
37a07aba5dSTimm Baeder };
38a07aba5dSTimm Baeder 
39a07aba5dSTimm Baeder /// Holds all information required to evaluate constexpr code in a module.
40a07aba5dSTimm Baeder class Context final {
41a07aba5dSTimm Baeder public:
42a07aba5dSTimm Baeder   /// Initialises the constexpr VM.
43a07aba5dSTimm Baeder   Context(ASTContext &Ctx);
44a07aba5dSTimm Baeder 
45a07aba5dSTimm Baeder   /// Cleans up the constexpr VM.
46a07aba5dSTimm Baeder   ~Context();
47a07aba5dSTimm Baeder 
48a07aba5dSTimm Baeder   /// Checks if a function is a potential constant expression.
49a07aba5dSTimm Baeder   bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
50a07aba5dSTimm Baeder 
51a07aba5dSTimm Baeder   /// Evaluates a toplevel expression as an rvalue.
52a07aba5dSTimm Baeder   bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
53a07aba5dSTimm Baeder 
54a07aba5dSTimm Baeder   /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
5583fea8b8STimm Baeder   bool evaluate(State &Parent, const Expr *E, APValue &Result,
5683fea8b8STimm Baeder                 ConstantExprKind Kind);
57a07aba5dSTimm Baeder 
58a07aba5dSTimm Baeder   /// Evaluates a toplevel initializer.
59a07aba5dSTimm Baeder   bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
60a07aba5dSTimm Baeder 
61a07aba5dSTimm Baeder   /// Returns the AST context.
62a07aba5dSTimm Baeder   ASTContext &getASTContext() const { return Ctx; }
63a07aba5dSTimm Baeder   /// Returns the language options.
64a07aba5dSTimm Baeder   const LangOptions &getLangOpts() const;
65a07aba5dSTimm Baeder   /// Returns the interpreter stack.
66a07aba5dSTimm Baeder   InterpStack &getStack() { return Stk; }
67a07aba5dSTimm Baeder   /// Returns CHAR_BIT.
68a07aba5dSTimm Baeder   unsigned getCharBit() const;
69a07aba5dSTimm Baeder   /// Return the floating-point semantics for T.
70a07aba5dSTimm Baeder   const llvm::fltSemantics &getFloatSemantics(QualType T) const;
71a07aba5dSTimm Baeder   /// Return the size of T in bits.
72a07aba5dSTimm Baeder   uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
73a07aba5dSTimm Baeder 
74a07aba5dSTimm Baeder   /// Classifies a type.
75a07aba5dSTimm Baeder   std::optional<PrimType> classify(QualType T) const;
76a07aba5dSTimm Baeder 
77a07aba5dSTimm Baeder   /// Classifies an expression.
78a07aba5dSTimm Baeder   std::optional<PrimType> classify(const Expr *E) const {
79a07aba5dSTimm Baeder     assert(E);
80a07aba5dSTimm Baeder     if (E->isGLValue()) {
81a07aba5dSTimm Baeder       if (E->getType()->isFunctionType())
82a07aba5dSTimm Baeder         return PT_FnPtr;
83a07aba5dSTimm Baeder       return PT_Ptr;
84a07aba5dSTimm Baeder     }
85a07aba5dSTimm Baeder 
86a07aba5dSTimm Baeder     return classify(E->getType());
87a07aba5dSTimm Baeder   }
88a07aba5dSTimm Baeder 
89a07aba5dSTimm Baeder   const CXXMethodDecl *
90a07aba5dSTimm Baeder   getOverridingFunction(const CXXRecordDecl *DynamicDecl,
91a07aba5dSTimm Baeder                         const CXXRecordDecl *StaticDecl,
92a07aba5dSTimm Baeder                         const CXXMethodDecl *InitialFunction) const;
93a07aba5dSTimm Baeder 
94a07aba5dSTimm Baeder   const Function *getOrCreateFunction(const FunctionDecl *FD);
95a07aba5dSTimm Baeder 
96a07aba5dSTimm Baeder   /// Returns whether we should create a global variable for the
97a07aba5dSTimm Baeder   /// given ValueDecl.
98a07aba5dSTimm Baeder   static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
99a07aba5dSTimm Baeder     if (const auto *V = dyn_cast<VarDecl>(VD))
100a07aba5dSTimm Baeder       return V->hasGlobalStorage() || V->isConstexpr();
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder     return false;
103a07aba5dSTimm Baeder   }
104a07aba5dSTimm Baeder 
105a07aba5dSTimm Baeder   /// Returns the program. This is only needed for unittests.
106a07aba5dSTimm Baeder   Program &getProgram() const { return *P.get(); }
107a07aba5dSTimm Baeder 
108a07aba5dSTimm Baeder   unsigned collectBaseOffset(const RecordDecl *BaseDecl,
109a07aba5dSTimm Baeder                              const RecordDecl *DerivedDecl) const;
110a07aba5dSTimm Baeder 
111a07aba5dSTimm Baeder   const Record *getRecord(const RecordDecl *D) const;
112a07aba5dSTimm Baeder 
113a07aba5dSTimm Baeder   unsigned getEvalID() const { return EvalID; }
114a07aba5dSTimm Baeder 
115a07aba5dSTimm Baeder private:
116a07aba5dSTimm Baeder   /// Runs a function.
117*82ed9c03STimm Baeder   bool Run(State &Parent, const Function *Func);
118a07aba5dSTimm Baeder 
119a07aba5dSTimm Baeder   /// Current compilation context.
120a07aba5dSTimm Baeder   ASTContext &Ctx;
121a07aba5dSTimm Baeder   /// Interpreter stack, shared across invocations.
122a07aba5dSTimm Baeder   InterpStack Stk;
123a07aba5dSTimm Baeder   /// Constexpr program.
124a07aba5dSTimm Baeder   std::unique_ptr<Program> P;
125a07aba5dSTimm Baeder   /// ID identifying an evaluation.
126a07aba5dSTimm Baeder   unsigned EvalID = 0;
127a07aba5dSTimm Baeder };
128a07aba5dSTimm Baeder 
129a07aba5dSTimm Baeder } // namespace interp
130a07aba5dSTimm Baeder } // namespace clang
131a07aba5dSTimm Baeder 
132a07aba5dSTimm Baeder #endif
133