brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · e2e4d5c Raw
223 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Definition of the interpreter state and entry point.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H14#define LLVM_CLANG_AST_INTERP_INTERPSTATE_H15 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"24#include "clang/AST/ASTDiagnostic.h"25#include "clang/AST/Expr.h"26#include "clang/AST/OptionalDiagnostic.h"27 28namespace clang {29namespace interp {30class Context;31class Function;32class InterpStack;33class InterpFrame;34class SourceMapper;35 36struct StdAllocatorCaller {37  const Expr *Call = nullptr;38  QualType AllocType;39  explicit operator bool() { return Call; }40};41 42/// Interpreter context.43class InterpState final : public State, public SourceMapper {44public:45  InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,46              SourceMapper *M = nullptr);47  InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx,48              const Function *Func);49 50  ~InterpState();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 Ctx.getASTContext(); }71  const LangOptions &getLangOpts() const {72    return Ctx.getASTContext().getLangOpts();73  }74 75  // Forward status checks and updates to the walker.76  bool keepEvaluatingAfterFailure() const override {77    return Parent.keepEvaluatingAfterFailure();78  }79  bool keepEvaluatingAfterSideEffect() const override {80    return Parent.keepEvaluatingAfterSideEffect();81  }82  bool noteUndefinedBehavior() override {83    return Parent.noteUndefinedBehavior();84  }85  bool inConstantContext() const;86  bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); }87  void setActiveDiagnostic(bool Flag) override {88    Parent.setActiveDiagnostic(Flag);89  }90  void setFoldFailureDiagnostic(bool Flag) override {91    Parent.setFoldFailureDiagnostic(Flag);92  }93  bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); }94  bool noteSideEffect() override { return Parent.noteSideEffect(); }95 96  /// Deallocates a pointer.97  void deallocate(Block *B);98 99  /// Delegates source mapping to the mapper.100  SourceInfo getSource(const Function *F, CodePtr PC) const override {101    if (M)102      return M->getSource(F, PC);103 104    assert(F && "Function cannot be null");105    return F->getSource(PC);106  }107 108  Context &getContext() const { return Ctx; }109 110  void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; }111 112  DynamicAllocator &getAllocator() {113    if (!Alloc) {114      Alloc = std::make_unique<DynamicAllocator>();115    }116 117    return *Alloc;118  }119 120  /// Diagnose any dynamic allocations that haven't been freed yet.121  /// Will return \c false if there were any allocations to diagnose,122  /// \c true otherwise.123  bool maybeDiagnoseDanglingAllocations();124 125  StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const;126 127  void *allocate(size_t Size, unsigned Align = 8) const {128    if (!Allocator)129      Allocator.emplace();130    return Allocator->Allocate(Size, Align);131  }132  template <typename T> T *allocate(size_t Num = 1) const {133    return static_cast<T *>(allocate(Num * sizeof(T), alignof(T)));134  }135 136  template <typename T> T allocAP(unsigned BitWidth) {137    unsigned NumWords = APInt::getNumWords(BitWidth);138    if (NumWords == 1)139      return T(BitWidth);140    uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));141    // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug142    return T(Mem, BitWidth);143  }144 145  Floating allocFloat(const llvm::fltSemantics &Sem) {146    if (Floating::singleWord(Sem))147      return Floating(llvm::APFloatBase::SemanticsToEnum(Sem));148 149    unsigned NumWords =150        APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem));151    uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));152    // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug153    return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem));154  }155 156private:157  friend class EvaluationResult;158  friend class InterpStateCCOverride;159  /// AST Walker state.160  State &Parent;161  /// Dead block chain.162  DeadBlock *DeadBlocks = nullptr;163  /// Reference to the offset-source mapping.164  SourceMapper *M;165  /// Allocator used for dynamic allocations performed via the program.166  std::unique_ptr<DynamicAllocator> Alloc;167 168public:169  /// Reference to the module containing all bytecode.170  Program &P;171  /// Temporary stack.172  InterpStack &Stk;173  /// Interpreter Context.174  Context &Ctx;175  /// Bottom function frame.176  InterpFrame BottomFrame;177  /// The current frame.178  InterpFrame *Current = nullptr;179  /// Source location of the evaluating expression180  SourceLocation EvalLocation;181  /// Declaration we're initializing/evaluting, if any.182  const VarDecl *EvaluatingDecl = nullptr;183  /// Things needed to do speculative execution.184  SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;185  unsigned SpeculationDepth = 0;186  std::optional<bool> ConstantContextOverride;187 188  llvm::SmallVector<189      std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>190      SeenGlobalTemporaries;191 192  /// List of blocks we're currently running either constructors or destructors193  /// for.194  llvm::SmallVector<const Block *> InitializingBlocks;195 196  mutable std::optional<llvm::BumpPtrAllocator> Allocator;197};198 199class InterpStateCCOverride final {200public:201  InterpStateCCOverride(InterpState &Ctx, bool Value)202      : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) {203    // We only override this if the new value is true.204    Enabled = Value;205    if (Enabled)206      Ctx.ConstantContextOverride = Value;207  }208  ~InterpStateCCOverride() {209    if (Enabled)210      Ctx.ConstantContextOverride = OldCC;211  }212 213private:214  bool Enabled;215  InterpState &Ctx;216  std::optional<bool> OldCC;217};218 219} // namespace interp220} // namespace clang221 222#endif223