clang 22.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#include "clang/AST/APValue.h"
25#include "clang/AST/Expr.h"
27
28namespace clang {
29namespace interp {
30class Context;
31class Function;
32class InterpStack;
33class InterpFrame;
34class SourceMapper;
35
37 const Expr *Call = nullptr;
39 explicit operator bool() { return Call; }
40};
41
42/// Interpreter context.
43class InterpState final : public State, public SourceMapper {
44public:
46 SourceMapper *M = nullptr);
48 const Function *Func);
49
51
52 void cleanup();
53
54 InterpState(const InterpState &) = delete;
55 InterpState &operator=(const InterpState &) = delete;
56
57 bool diagnosing() const { return getEvalStatus().Diag != nullptr; }
58
59 // Stack frame accessors.
60 Frame *getCurrentFrame() override;
61 unsigned getCallStackDepth() override {
62 return Current ? (Current->getDepth() + 1) : 1;
63 }
64 const Frame *getBottomFrame() const override { return &BottomFrame; }
65
66 // Access objects from the walker context.
67 Expr::EvalStatus &getEvalStatus() const override {
68 return Parent.getEvalStatus();
69 }
70 ASTContext &getASTContext() const override { return Parent.getASTContext(); }
71
72 // Forward status checks and updates to the walker.
73 bool checkingForUndefinedBehavior() const override {
74 return Parent.checkingForUndefinedBehavior();
75 }
76 bool keepEvaluatingAfterFailure() const override {
77 return Parent.keepEvaluatingAfterFailure();
78 }
79 bool keepEvaluatingAfterSideEffect() const override {
80 return Parent.keepEvaluatingAfterSideEffect();
81 }
83 return Parent.checkingPotentialConstantExpression();
84 }
85 bool noteUndefinedBehavior() override {
86 return Parent.noteUndefinedBehavior();
87 }
88 bool inConstantContext() const;
89 bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }
90 void setActiveDiagnostic(bool Flag) override {
91 Parent.setActiveDiagnostic(Flag);
92 }
93 void setFoldFailureDiagnostic(bool Flag) override {
94 Parent.setFoldFailureDiagnostic(Flag);
95 }
96 bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }
97 bool noteSideEffect() override { return Parent.noteSideEffect(); }
98
99 /// Reports overflow and return true if evaluation should continue.
100 bool reportOverflow(const Expr *E, const llvm::APSInt &Value);
101
102 /// Deallocates a pointer.
103 void deallocate(Block *B);
104
105 /// Delegates source mapping to the mapper.
106 SourceInfo getSource(const Function *F, CodePtr PC) const override {
107 if (M)
108 return M->getSource(F, PC);
109
110 assert(F && "Function cannot be null");
111 return F->getSource(PC);
112 }
113
114 Context &getContext() const { return Ctx; }
115
117
119 if (!Alloc) {
120 Alloc = std::make_unique<DynamicAllocator>();
121 }
122
123 return *Alloc.get();
124 }
125
126 /// Diagnose any dynamic allocations that haven't been freed yet.
127 /// Will return \c false if there were any allocations to diagnose,
128 /// \c true otherwise.
130
131 StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const;
132
133 void *allocate(size_t Size, unsigned Align = 8) const {
134 return Allocator.Allocate(Size, Align);
135 }
136 template <typename T> T *allocate(size_t Num = 1) const {
137 return static_cast<T *>(allocate(Num * sizeof(T), alignof(T)));
138 }
139
140 template <typename T> T allocAP(unsigned BitWidth) {
141 unsigned NumWords = APInt::getNumWords(BitWidth);
142 if (NumWords == 1)
143 return T(BitWidth);
144 uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
145 // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
146 return T(Mem, BitWidth);
147 }
148
149 Floating allocFloat(const llvm::fltSemantics &Sem) {
150 if (Floating::singleWord(Sem))
151 return Floating(llvm::APFloatBase::SemanticsToEnum(Sem));
152
153 unsigned NumWords =
154 APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem));
155 uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
156 // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
157 return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem));
158 }
159
160private:
161 friend class EvaluationResult;
163 /// AST Walker state.
164 State &Parent;
165 /// Dead block chain.
166 DeadBlock *DeadBlocks = nullptr;
167 /// Reference to the offset-source mapping.
168 SourceMapper *M;
169 /// Allocator used for dynamic allocations performed via the program.
170 std::unique_ptr<DynamicAllocator> Alloc;
171
172public:
173 /// Reference to the module containing all bytecode.
175 /// Temporary stack.
177 /// Interpreter Context.
179 /// Bottom function frame.
181 /// The current frame.
183 /// Source location of the evaluating expression
185 /// Declaration we're initializing/evaluting, if any.
186 const VarDecl *EvaluatingDecl = nullptr;
187 /// Things needed to do speculative execution.
189 unsigned SpeculationDepth = 0;
190 std::optional<bool> ConstantContextOverride;
191
193 std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>
195
196 /// List of blocks we're currently running either constructors or destructors
197 /// for.
199
200 mutable llvm::BumpPtrAllocator Allocator;
201};
202
204public:
206 : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {
207 // We only override this if the new value is true.
208 Enabled = Value;
209 if (Enabled)
210 Ctx.ConstantContextOverride = Value;
211 }
213 if (Enabled)
214 Ctx.ConstantContextOverride = OldCC;
215 }
216
217private:
218 bool Enabled;
219 InterpState &Ctx;
220 std::optional<bool> OldCC;
221};
222
223} // namespace interp
224} // namespace clang
225
226#endif
NodeId Parent
Definition: ASTDiff.cpp:191
Expr * E
Implements a partial diagnostic which may not be emitted.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
This represents one expression.
Definition: Expr.h:112
A (possibly-)qualified type.
Definition: TypeBase.h:937
Encodes a location in the source.
Represents a variable declaration or definition.
Definition: Decl.h:925
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.
Definition: InterpBlock.h:200
Manages dynamic memory allocations done during bytecode interpretation.
Defines the result of an evaluation.
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition: Floating.h:35
bool singleWord() const
Definition: Floating.h:106
Base class for stack frames, shared between VM and walker.
Definition: Frame.h:25
Bytecode function.
Definition: Function.h:86
SourceInfo getSource(CodePtr PC) const
Returns the source information at a given PC.
Definition: Function.cpp:63
Frame storing local variables.
Definition: InterpFrame.h:26
unsigned getDepth() const
Definition: InterpFrame.h:128
Stack frame storing temporaries and parameters.
Definition: InterpStack.h:25
InterpStateCCOverride(InterpState &Ctx, bool Value)
Definition: InterpState.h:205
Interpreter context.
Definition: InterpState.h:43
const Frame * getBottomFrame() const override
Definition: InterpState.h:64
SmallVectorImpl< PartialDiagnosticAt > * PrevDiags
Things needed to do speculative execution.
Definition: InterpState.h:188
llvm::BumpPtrAllocator Allocator
Definition: InterpState.h:200
unsigned getCallStackDepth() override
Definition: InterpState.h:61
Expr::EvalStatus & getEvalStatus() const override
Definition: InterpState.h:67
InterpFrame BottomFrame
Bottom function frame.
Definition: InterpState.h:180
Context & getContext() const
Definition: InterpState.h:114
bool keepEvaluatingAfterFailure() const override
Definition: InterpState.h:76
bool reportOverflow(const Expr *E, const llvm::APSInt &Value)
Reports overflow and return true if evaluation should continue.
Definition: InterpState.cpp:68
bool noteUndefinedBehavior() override
Definition: InterpState.h:85
DynamicAllocator & getAllocator()
Definition: InterpState.h:118
Context & Ctx
Interpreter Context.
Definition: InterpState.h:178
void * allocate(size_t Size, unsigned Align=8) const
Definition: InterpState.h:133
Floating allocFloat(const llvm::fltSemantics &Sem)
Definition: InterpState.h:149
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
Definition: InterpState.h:198
ASTContext & getASTContext() const override
Definition: InterpState.h:70
SourceInfo getSource(const Function *F, CodePtr PC) const override
Delegates source mapping to the mapper.
Definition: InterpState.h:106
Frame * getCurrentFrame() override
Definition: InterpState.cpp:66
InterpState(const InterpState &)=delete
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
Definition: InterpState.h:194
InterpStack & Stk
Temporary stack.
Definition: InterpState.h:176
bool maybeDiagnoseDanglingAllocations()
Diagnose any dynamic allocations that haven't been freed yet.
SourceLocation EvalLocation
Source location of the evaluating expression.
Definition: InterpState.h:184
bool keepEvaluatingAfterSideEffect() const override
Definition: InterpState.h:79
bool noteSideEffect() override
Definition: InterpState.h:97
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
Definition: InterpState.h:186
InterpFrame * Current
The current frame.
Definition: InterpState.h:182
bool hasActiveDiagnostic() override
Definition: InterpState.h:89
std::optional< bool > ConstantContextOverride
Definition: InterpState.h:190
void setActiveDiagnostic(bool Flag) override
Definition: InterpState.h:90
bool checkingForUndefinedBehavior() const override
Definition: InterpState.h:73
void setFoldFailureDiagnostic(bool Flag) override
Definition: InterpState.h:93
InterpState & operator=(const InterpState &)=delete
T * allocate(size_t Num=1) const
Definition: InterpState.h:136
void deallocate(Block *B)
Deallocates a pointer.
Definition: InterpState.cpp:74
T allocAP(unsigned BitWidth)
Definition: InterpState.h:140
void setEvalLocation(SourceLocation SL)
Definition: InterpState.h:116
bool checkingPotentialConstantExpression() const override
Definition: InterpState.h:82
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
bool inConstantContext() const
Definition: InterpState.cpp:31
bool hasPriorDiagnostic() override
Definition: InterpState.h:96
Program & P
Reference to the module containing all bytecode.
Definition: InterpState.h:174
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:73
Interface for classes which map locations to sources.
Definition: Source.h:99
virtual SourceInfo getSource(const Function *F, CodePtr PC) const =0
Returns source information for a given PC in a function.
Interface for the VM to interact with the AST walker's context.
Definition: State.h:58
#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