21 : Ctx(Ctx),
P(
P), S(
Parent,
P, Stk, Ctx, this), EvalResult(&Ctx) {
28 for (
auto &[K,
V] : Locals) {
41 bool ConvertResultToRValue) {
43 this->ConvertResultToRValue = ConvertResultToRValue && !isa<ConstantExpr>(
E);
44 this->CheckFullyInitialized = isa<ConstantExpr>(
E);
45 EvalResult.setSource(
E);
50 EvalResult.setInvalid();
53 return std::move(this->EvalResult);
58 this->CheckFullyInitialized = CheckFullyInitialized;
60 EvalResult.setSource(VD);
67 this->ConvertResultToRValue =
false;
69 EvalResult.setSource(VD);
72 EvalResult.setInvalid();
75 updateGlobalTemporaries();
76 return std::move(this->EvalResult);
85 auto Memory = std::make_unique<char[]>(
sizeof(
Block) +
D->getAllocSize());
100 unsigned Off = Locals.size();
101 Locals.insert({Off, std::move(Memory)});
123 CurrentLabel = ActiveLabel =
Label;
130 CurrentLabel =
Label;
135 return S.maybeDiagnoseDanglingAllocations();
138template <PrimType OpType>
bool EvalEmitter::emitRet(
const SourceInfo &Info) {
150template <>
bool EvalEmitter::emitRet<PT_Ptr>(
const SourceInfo &Info) {
165 if (ConvertResultToRValue) {
180 if (std::optional<APValue>
V =
182 EvalResult.setValue(*
V);
192template <>
bool EvalEmitter::emitRet<PT_FnPtr>(
const SourceInfo &Info) {
203bool EvalEmitter::emitRetVoid(
const SourceInfo &Info) {
206 EvalResult.setValid();
210bool EvalEmitter::emitRetValue(
const SourceInfo &Info) {
221 if (std::optional<APValue> APV =
223 EvalResult.setValue(*APV);
227 EvalResult.setInvalid();
231bool EvalEmitter::emitGetPtrLocal(uint32_t I,
const SourceInfo &Info) {
235 Block *B = getLocal(I);
240template <PrimType OpType>
241bool EvalEmitter::emitGetLocal(uint32_t I,
const SourceInfo &Info) {
247 Block *B = getLocal(I);
252template <PrimType OpType>
253bool EvalEmitter::emitSetLocal(uint32_t I,
const SourceInfo &Info) {
259 Block *B = getLocal(I);
267bool EvalEmitter::emitDestroy(uint32_t I,
const SourceInfo &Info) {
284void EvalEmitter::updateGlobalTemporaries() {
286 if (std::optional<unsigned> GlobalIndex = P.
getGlobal(
E)) {
288 APValue *Cached = Temp->getOrCreateValue(
true);
294 if (std::optional<APValue> APV =
295 Ptr.
toRValue(Ctx, Temp->getTemporaryExpr()->getType()))
308#include "Opcodes.inc"
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static bool checkReturnState(InterpState &S)
static bool CheckFullyInitialized(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value)
Check that this evaluated value is fully-initialized and can be loaded by an lvalue-to-rvalue convers...
#define TYPE_SWITCH(Expr, B)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
A (possibly-)qualified type.
bool isPointerType() const
bool isObjCObjectPointerType() const
Represents a variable declaration or definition.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
A memory block, either on the stack or in the heap.
void invokeDtor()
Invokes the Destructor.
std::byte * data()
Returns a pointer to the stored data.
void invokeCtor()
Invokes the constructor.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
unsigned getEvalID() const
The Evaluation ID this block was created in.
Pointer into the code segment.
Holds all information required to evaluate constexpr code in a module.
ASTContext & getASTContext() const
Returns the AST context.
std::optional< PrimType > classify(QualType T) const
Classifies a type.
unsigned getEvalID() const
bool jump(const LabelTy &Label)
EvaluationResult interpretExpr(const Expr *E, bool ConvertResultToRValue=false)
EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized)
virtual bool visitExpr(const Expr *E)=0
Methods implemented by the compiler.
bool jumpFalse(const LabelTy &Label)
Local createLocal(Descriptor *D)
Callback for registering a local.
void emitLabel(LabelTy Label)
Define a label.
bool isActive() const
Since expressions can only jump forward, predicated execution is used to deal with if-else statements...
bool fallthrough(const LabelTy &Label)
void cleanup()
Clean up all resources.
LabelTy getLabel()
Create a label.
EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk)
virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext)=0
llvm::SmallVector< SmallVector< Local, 8 >, 2 > Descriptors
Local descriptors.
bool jumpTrue(const LabelTy &Label)
Emits jumps.
Defines the result of an evaluation.
QualType getSourceType() const
bool checkReturnValue(InterpState &S, const Context &Ctx, const Pointer &Ptr, const SourceInfo &Info)
Check that none of the blocks the given pointer (transitively) points to are dynamically allocated.
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const
Check that all subobjects of the given pointer have been initialized.
Frame storing local variables.
Stack frame storing temporaries and parameters.
T pop()
Returns the value from the top of the stack and removes it.
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
InterpStack & Stk
Temporary stack.
bool inConstantContext() const
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
void deallocate(Block *B)
Deallocates a pointer.
ASTContext & getCtx() const override
void setEvalLocation(SourceLocation SL)
A pointer to a memory block, live or dead.
bool isConst() const
Checks if an object or a subfield is mutable.
T & deref() const
Dereferences the pointer, if it's live.
bool isZero() const
Checks if the pointer is null.
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
bool isDereferencable() const
Whether this block can be read from at all.
bool isBlockPointer() const
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
const Block * block() const
The program contains and links the bytecode for all functions.
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Describes the statement/declaration an opcode was generated from.
Interface for the VM to interact with the AST walker's context.
const LangOptions & getLangOpts() const
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Inline descriptor embedded in structures and arrays.
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned IsBase
Flag indicating if the field is an embedded base class.
unsigned Offset
Offset inside the structure/array.
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
unsigned IsConst
Flag indicating if the storage is constant or not.
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).
Mapping from primitive types to their representation.
Information about a local's storage.
unsigned Offset
Offset of the local in frame.