20 : Ctx(Ctx),
P(
P), S(
Parent,
P, Stk, Ctx, this), EvalResult(&Ctx) {}
23 for (
auto &
V : Locals) {
36 bool ConvertResultToRValue,
37 bool DestroyToplevelScope) {
39 this->ConvertResultToRValue = ConvertResultToRValue && !isa<ConstantExpr>(
E);
40 this->CheckFullyInitialized = isa<ConstantExpr>(
E);
41 EvalResult.setSource(
E);
43 if (!this->
visitExpr(E, DestroyToplevelScope)) {
46 EvalResult.setInvalid();
49 return std::move(this->EvalResult);
54 this->CheckFullyInitialized = CheckFullyInitialized;
57 EvalResult.setSource(VD);
64 this->ConvertResultToRValue =
false;
66 EvalResult.setSource(VD);
69 EvalResult.setInvalid();
72 updateGlobalTemporaries();
73 return std::move(this->EvalResult);
80 this->ConvertResultToRValue =
false;
81 this->CheckFullyInitialized =
false;
83 EvalResult.setSource(
E);
88 EvalResult.setInvalid();
91 return std::move(this->EvalResult);
98 this->
Params.insert({PD, {0,
false}});
110 auto Memory = std::make_unique<char[]>(
sizeof(
Block) +
D->getAllocSize());
125 unsigned Off = Locals.size();
126 Locals.push_back(std::move(Memory));
148 CurrentLabel = ActiveLabel =
Label;
155 CurrentLabel =
Label;
160 size_t StackSizeBefore = S.
Stk.
size();
161 const Expr *Arg =
E->getArg(0);
162 if (!this->
visit(Arg)) {
177 if (!this->emitPop(
T,
E))
182template <PrimType OpType>
bool EvalEmitter::emitRet(
const SourceInfo &Info) {
191template <>
bool EvalEmitter::emitRet<PT_Ptr>(
const SourceInfo &Info) {
204 return (*this->PtrCB)(Ptr);
212 if (ConvertResultToRValue) {
225 if (std::optional<APValue>
V =
227 EvalResult.takeValue(std::move(*
V));
249bool EvalEmitter::emitRetVoid(
const SourceInfo &Info) {
250 EvalResult.setValid();
254bool EvalEmitter::emitRetValue(
const SourceInfo &Info) {
262 if (std::optional<APValue> APV =
264 EvalResult.takeValue(std::move(*APV));
268 EvalResult.setInvalid();
272bool EvalEmitter::emitGetPtrLocal(uint32_t I,
const SourceInfo &Info) {
276 Block *B = getLocal(I);
281template <PrimType OpType>
282bool EvalEmitter::emitGetLocal(uint32_t I,
const SourceInfo &Info) {
288 Block *B = getLocal(I);
297template <PrimType OpType>
298bool EvalEmitter::emitSetLocal(uint32_t I,
const SourceInfo &Info) {
304 Block *B = getLocal(I);
312bool EvalEmitter::emitDestroy(uint32_t I,
const SourceInfo &Info) {
329void EvalEmitter::updateGlobalTemporaries() {
331 if (std::optional<unsigned> GlobalIndex = P.
getGlobal(
E)) {
333 APValue *Cached = Temp->getOrCreateValue(
true);
339 if (std::optional<APValue> APV =
340 Ptr.
toRValue(Ctx, Temp->getTemporaryExpr()->getType()))
353#include "Opcodes.inc"
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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],...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getLocation() const
This represents one expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
ArrayRef< ParmVarDecl * > parameters() const
Represents a parameter to a function.
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.
bool isStatic() const
Checks if the block has static storage duration.
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.
Holds all information required to evaluate constexpr code in a module.
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
unsigned getEvalID() const
bool jump(const LabelTy &Label)
EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized)
EvaluationResult interpretExpr(const Expr *E, bool ConvertResultToRValue=false, bool DestroyToplevelScope=false)
bool jumpFalse(const LabelTy &Label)
virtual bool visit(const Expr *E)=0
bool speculate(const CallExpr *E, const LabelTy &EndLabel)
Speculative execution.
Local createLocal(Descriptor *D)
Callback for registering a local.
bool interpretCall(const FunctionDecl *FD, const Expr *E)
Interpret the given expression as if it was in the body of the given function, i.e.
llvm::function_ref< bool(const Pointer &)> PtrCallback
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...
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope)=0
Methods implemented by the compiler.
bool fallthrough(const LabelTy &Label)
void cleanup()
Clean up all resources.
LabelTy getLabel()
Create a label.
EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB)
Interpret the given Expr to a Pointer.
EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk)
virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext)=0
llvm::DenseMap< const ParmVarDecl *, ParamOffset > Params
Parameter indices.
virtual bool emitBool(bool V, const Expr *E)=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.
Stack frame storing temporaries and parameters.
void clearTo(size_t NewSize)
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.
size_t size() const
Returns the size of the stack in bytes.
ASTContext & getASTContext() const override
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
InterpStack & Stk
Temporary stack.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
void deallocate(Block *B)
Deallocates a pointer.
void setEvalLocation(SourceLocation SL)
bool inConstantContext() const
PrimType value_or(PrimType PT) const
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 isLive() const
Checks if the pointer is 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.
bool isTemporary() const
Checks if the storage is temporary.
const Block * block() const
bool isFunctionPointer() 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.
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
PrimType
Enumeration of the primitive types of the VM.
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
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.