Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpState.h
213799 views
//===--- InterpState.h - Interpreter state for the constexpr VM -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Definition of the interpreter state and entry point.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H13#define LLVM_CLANG_AST_INTERP_INTERPSTATE_H1415#include "Context.h"16#include "DynamicAllocator.h"17#include "Floating.h"18#include "Function.h"19#include "InterpFrame.h"20#include "InterpStack.h"21#include "State.h"22#include "clang/AST/APValue.h"23#include "clang/AST/ASTDiagnostic.h"24#include "clang/AST/Expr.h"25#include "clang/AST/OptionalDiagnostic.h"2627namespace clang {28namespace interp {29class Context;30class Function;31class InterpStack;32class InterpFrame;33class SourceMapper;3435struct StdAllocatorCaller {36const Expr *Call = nullptr;37QualType AllocType;38explicit operator bool() { return Call; }39};4041/// Interpreter context.42class InterpState final : public State, public SourceMapper {43public:44InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,45SourceMapper *M = nullptr);46InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,47const Function *Func);4849~InterpState();5051void cleanup();5253InterpState(const InterpState &) = delete;54InterpState &operator=(const InterpState &) = delete;5556bool diagnosing() const { return getEvalStatus().Diag != nullptr; }5758// Stack frame accessors.59Frame *getSplitFrame() { return Parent.getCurrentFrame(); }60Frame *getCurrentFrame() override;61unsigned getCallStackDepth() override {62return Current ? (Current->getDepth() + 1) : 1;63}64const Frame *getBottomFrame() const override {65return Parent.getBottomFrame();66}6768// Access objects from the walker context.69Expr::EvalStatus &getEvalStatus() const override {70return Parent.getEvalStatus();71}72ASTContext &getASTContext() const override { return Parent.getASTContext(); }7374// Forward status checks and updates to the walker.75bool checkingForUndefinedBehavior() const override {76return Parent.checkingForUndefinedBehavior();77}78bool keepEvaluatingAfterFailure() const override {79return Parent.keepEvaluatingAfterFailure();80}81bool keepEvaluatingAfterSideEffect() const override {82return Parent.keepEvaluatingAfterSideEffect();83}84bool checkingPotentialConstantExpression() const override {85return Parent.checkingPotentialConstantExpression();86}87bool noteUndefinedBehavior() override {88return Parent.noteUndefinedBehavior();89}90bool inConstantContext() const;91bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }92void setActiveDiagnostic(bool Flag) override {93Parent.setActiveDiagnostic(Flag);94}95void setFoldFailureDiagnostic(bool Flag) override {96Parent.setFoldFailureDiagnostic(Flag);97}98bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }99bool noteSideEffect() override { return Parent.noteSideEffect(); }100101/// Reports overflow and return true if evaluation should continue.102bool reportOverflow(const Expr *E, const llvm::APSInt &Value);103104/// Deallocates a pointer.105void deallocate(Block *B);106107/// Delegates source mapping to the mapper.108SourceInfo getSource(const Function *F, CodePtr PC) const override {109if (M)110return M->getSource(F, PC);111112assert(F && "Function cannot be null");113return F->getSource(PC);114}115116Context &getContext() const { return Ctx; }117118void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; }119120DynamicAllocator &getAllocator() { return Alloc; }121122/// Diagnose any dynamic allocations that haven't been freed yet.123/// Will return \c false if there were any allocations to diagnose,124/// \c true otherwise.125bool maybeDiagnoseDanglingAllocations();126127StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const;128129void *allocate(size_t Size, unsigned Align = 8) const {130return Allocator.Allocate(Size, Align);131}132template <typename T> T *allocate(size_t Num = 1) const {133return static_cast<T *>(allocate(Num * sizeof(T), alignof(T)));134}135136template <typename T> T allocAP(unsigned BitWidth) {137unsigned NumWords = APInt::getNumWords(BitWidth);138if (NumWords == 1)139return T(BitWidth);140uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));141// std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug142return T(Mem, BitWidth);143}144145Floating allocFloat(const llvm::fltSemantics &Sem) {146if (Floating::singleWord(Sem))147return Floating(llvm::APFloatBase::SemanticsToEnum(Sem));148149unsigned NumWords =150APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem));151uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));152// std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug153return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem));154}155156private:157friend class EvaluationResult;158friend class InterpStateCCOverride;159/// AST Walker state.160State &Parent;161/// Dead block chain.162DeadBlock *DeadBlocks = nullptr;163/// Reference to the offset-source mapping.164SourceMapper *M;165/// Allocator used for dynamic allocations performed via the program.166DynamicAllocator Alloc;167168public:169/// Reference to the module containing all bytecode.170Program &P;171/// Temporary stack.172InterpStack &Stk;173/// Interpreter Context.174Context &Ctx;175/// Bottom function frame.176InterpFrame BottomFrame;177/// The current frame.178InterpFrame *Current = nullptr;179/// Source location of the evaluating expression180SourceLocation EvalLocation;181/// Declaration we're initializing/evaluting, if any.182const VarDecl *EvaluatingDecl = nullptr;183/// Things needed to do speculative execution.184SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;185unsigned SpeculationDepth = 0;186std::optional<bool> ConstantContextOverride;187188llvm::SmallVector<189std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>190SeenGlobalTemporaries;191192/// List of blocks we're currently running either constructors or destructors193/// for.194llvm::SmallVector<const Block *> InitializingBlocks;195196mutable llvm::BumpPtrAllocator Allocator;197};198199class InterpStateCCOverride final {200public:201InterpStateCCOverride(InterpState &Ctx, bool Value)202: Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {203// We only override this if the new value is true.204Enabled = Value;205if (Enabled)206Ctx.ConstantContextOverride = Value;207}208~InterpStateCCOverride() {209if (Enabled)210Ctx.ConstantContextOverride = OldCC;211}212213private:214bool Enabled;215InterpState &Ctx;216std::optional<bool> OldCC;217};218219} // namespace interp220} // namespace clang221222#endif223224225