clang 23.0.0git
InterpState.h
Go to the documentation of this file.
1//===--- InterpState.h - Interpreter state for the constexpr VM -*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Definition of the interpreter state and entry point.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H
14#define LLVM_CLANG_AST_INTERP_INTERPSTATE_H
15
16#include "Context.h"
17#include "DynamicAllocator.h"
18#include "Floating.h"
19#include "Function.h"
20#include "InterpFrame.h"
21#include "InterpStack.h"
22#include "State.h"
23
24namespace clang {
25namespace interp {
26class Context;
27class SourceMapper;
28
30 const Expr *Call = nullptr;
32 explicit operator bool() { return Call; }
33};
34
35/// Interpreter context.
36class InterpState final : public State, public SourceMapper {
37public:
39 SourceMapper *M = nullptr);
41 const Function *Func);
42
44
45 void cleanup();
46
47 InterpState(const InterpState &) = delete;
48 InterpState &operator=(const InterpState &) = delete;
49
50 bool diagnosing() const { return getEvalStatus().Diag != nullptr; }
51
52 // Stack frame accessors.
53 Frame *getCurrentFrame() override;
54 unsigned getCallStackDepth() override {
55 return Current ? (Current->getDepth() + 1) : 1;
56 }
57 const Frame *getBottomFrame() const override { return &BottomFrame; }
58
59 // Access objects from the walker context.
60 Expr::EvalStatus &getEvalStatus() const override {
61 return Parent.getEvalStatus();
62 }
63 ASTContext &getASTContext() const override { return Ctx.getASTContext(); }
64 const LangOptions &getLangOpts() const {
65 return Ctx.getASTContext().getLangOpts();
66 }
67
68 // Forward status checks and updates to the walker.
69 bool keepEvaluatingAfterFailure() const override {
70 return Parent.keepEvaluatingAfterFailure();
71 }
72 bool keepEvaluatingAfterSideEffect() const override {
73 return Parent.keepEvaluatingAfterSideEffect();
74 }
75 bool noteUndefinedBehavior() override {
76 return Parent.noteUndefinedBehavior();
77 }
78 bool inConstantContext() const;
79 bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }
80 void setActiveDiagnostic(bool Flag) override {
81 Parent.setActiveDiagnostic(Flag);
82 }
83 void setFoldFailureDiagnostic(bool Flag) override {
84 Parent.setFoldFailureDiagnostic(Flag);
85 }
86 bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }
87 bool noteSideEffect() override { return Parent.noteSideEffect(); }
88
89 /// Deallocates a pointer.
90 void deallocate(Block *B);
91
92 /// Delegates source mapping to the mapper.
93 SourceInfo getSource(const Function *F, CodePtr PC) const override {
94 if (M)
95 return M->getSource(F, PC);
96
97 assert(F && "Function cannot be null");
98 return F->getSource(PC);
99 }
100
101 Context &getContext() const { return Ctx; }
102
104
106 if (!Alloc) {
107 Alloc = std::make_unique<DynamicAllocator>();
108 }
109
110 return *Alloc;
111 }
112
113 /// Diagnose any dynamic allocations that haven't been freed yet.
114 /// Will return \c false if there were any allocations to diagnose,
115 /// \c true otherwise.
117
118 StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const;
119
120 void *allocate(size_t Size, unsigned Align = 8) const {
121 if (!Allocator)
122 Allocator.emplace();
123 return Allocator->Allocate(Size, Align);
124 }
125 template <typename T> T *allocate(size_t Num = 1) const {
126 return static_cast<T *>(allocate(Num * sizeof(T), alignof(T)));
127 }
128
129 template <typename T> T allocAP(unsigned BitWidth) {
130 unsigned NumWords = APInt::getNumWords(BitWidth);
131 if (NumWords == 1)
132 return T(BitWidth);
133 uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
134 // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
135 return T(Mem, BitWidth);
136 }
137
138 Floating allocFloat(const llvm::fltSemantics &Sem) {
139 if (Floating::singleWord(Sem))
140 return Floating(llvm::APFloatBase::SemanticsToEnum(Sem));
141
142 unsigned NumWords =
143 APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem));
144 uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
145 // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
146 return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem));
147 }
148
149private:
150 friend class EvaluationResult;
152 /// AST Walker state.
153 State &Parent;
154 /// Dead block chain.
155 DeadBlock *DeadBlocks = nullptr;
156 /// Reference to the offset-source mapping.
157 SourceMapper *M;
158 /// Allocator used for dynamic allocations performed via the program.
159 std::unique_ptr<DynamicAllocator> Alloc;
160 /// Allocator for everything else, e.g. floating-point values.
161 mutable std::optional<llvm::BumpPtrAllocator> Allocator;
162
163public:
164 /// Reference to the module containing all bytecode.
166 /// Temporary stack.
168 /// Interpreter Context.
170 /// Bottom function frame.
172 /// The current frame.
174 /// Source location of the evaluating expression
176 /// Declaration we're initializing/evaluting, if any.
177 const VarDecl *EvaluatingDecl = nullptr;
178 /// Things needed to do speculative execution.
180 unsigned SpeculationDepth = 0;
181 std::optional<bool> ConstantContextOverride;
182
184 std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>
186
187 /// List of blocks we're currently running either constructors or destructors
188 /// for.
190};
191
193public:
195 : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {
196 // We only override this if the new value is true.
197 Enabled = Value;
198 if (Enabled)
199 Ctx.ConstantContextOverride = Value;
200 }
202 if (Enabled)
203 Ctx.ConstantContextOverride = OldCC;
204 }
205
206private:
207 bool Enabled;
208 InterpState &Ctx;
209 std::optional<bool> OldCC;
210};
211
212} // namespace interp
213} // namespace clang
214
215#endif
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
This represents one expression.
Definition Expr.h:112
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A (possibly-)qualified type.
Definition TypeBase.h:937
Encodes a location in the source.
Represents a variable declaration or definition.
Definition Decl.h:926
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
Pointer into the code segment.
Definition Source.h:30
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:41
Descriptor for a dead block.
Manages dynamic memory allocations done during bytecode interpretation.
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition Floating.h:35
bool singleWord() const
Definition Floating.h:107
Base class for stack frames, shared between VM and walker.
Definition Frame.h:25
Bytecode function.
Definition Function.h:88
SourceInfo getSource(CodePtr PC) const
Returns the source information at a given PC.
Definition Function.cpp:63
Frame storing local variables.
Definition InterpFrame.h:27
Stack frame storing temporaries and parameters.
Definition InterpStack.h:25
InterpStateCCOverride(InterpState &Ctx, bool Value)
Interpreter context.
Definition InterpState.h:36
const Frame * getBottomFrame() const override
Definition InterpState.h:57
SmallVectorImpl< PartialDiagnosticAt > * PrevDiags
Things needed to do speculative execution.
unsigned getCallStackDepth() override
Definition InterpState.h:54
Expr::EvalStatus & getEvalStatus() const override
Definition InterpState.h:60
InterpFrame BottomFrame
Bottom function frame.
Context & getContext() const
bool keepEvaluatingAfterFailure() const override
Definition InterpState.h:69
bool noteUndefinedBehavior() override
Definition InterpState.h:75
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
void * allocate(size_t Size, unsigned Align=8) const
Floating allocFloat(const llvm::fltSemantics &Sem)
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
ASTContext & getASTContext() const override
Definition InterpState.h:63
SourceInfo getSource(const Function *F, CodePtr PC) const override
Delegates source mapping to the mapper.
Definition InterpState.h:93
Frame * getCurrentFrame() override
InterpState(const InterpState &)=delete
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
InterpStack & Stk
Temporary stack.
bool maybeDiagnoseDanglingAllocations()
Diagnose any dynamic allocations that haven't been freed yet.
SourceLocation EvalLocation
Source location of the evaluating expression.
bool keepEvaluatingAfterSideEffect() const override
Definition InterpState.h:72
bool noteSideEffect() override
Definition InterpState.h:87
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx, SourceMapper *M=nullptr)
bool hasActiveDiagnostic() override
Definition InterpState.h:79
std::optional< bool > ConstantContextOverride
void setActiveDiagnostic(bool Flag) override
Definition InterpState.h:80
void setFoldFailureDiagnostic(bool Flag) override
Definition InterpState.h:83
InterpState & operator=(const InterpState &)=delete
friend class InterpStateCCOverride
T * allocate(size_t Num=1) const
void deallocate(Block *B)
Deallocates a pointer.
T allocAP(unsigned BitWidth)
const LangOptions & getLangOpts() const
Definition InterpState.h:64
void setEvalLocation(SourceLocation SL)
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
bool hasPriorDiagnostic() override
Definition InterpState.h:86
Program & P
Reference to the module containing all bytecode.
The program contains and links the bytecode for all functions.
Definition Program.h:36
Describes the statement/declaration an opcode was generated from.
Definition Source.h:74
Interface for classes which map locations to sources.
Definition Source.h:101
#define bool
Definition gpuintrin.h:32
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
EvalStatus is a struct with detailed info about an evaluation in progress.
Definition Expr.h:609
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition Expr.h:633