File: Context.h

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.6-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,304 kB
  • sloc: cpp: 7,438,677; ansic: 1,393,822; asm: 1,012,926; python: 241,650; f90: 86,635; objc: 75,479; lisp: 42,144; pascal: 17,286; sh: 10,027; ml: 5,082; perl: 4,730; awk: 3,523; makefile: 3,349; javascript: 2,251; xml: 892; fortran: 672
file content (132 lines) | stat: -rw-r--r-- 3,924 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//===--- Context.h - Context for the constexpr VM ---------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines the constexpr execution context.
//
// The execution context manages cached bytecode and the global context.
// It invokes the compiler and interpreter, propagating errors.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H
#define LLVM_CLANG_AST_INTERP_CONTEXT_H

#include "InterpStack.h"

namespace clang {
class ASTContext;
class LangOptions;
class FunctionDecl;
class VarDecl;
class APValue;

namespace interp {
class Function;
class Program;
class State;
enum PrimType : unsigned;

struct ParamOffset {
  unsigned Offset;
  bool IsPtr;
};

/// Holds all information required to evaluate constexpr code in a module.
class Context final {
public:
  /// Initialises the constexpr VM.
  Context(ASTContext &Ctx);

  /// Cleans up the constexpr VM.
  ~Context();

  /// Checks if a function is a potential constant expression.
  bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);

  /// Evaluates a toplevel expression as an rvalue.
  bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);

  /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
  bool evaluate(State &Parent, const Expr *E, APValue &Result,
                ConstantExprKind Kind);

  /// Evaluates a toplevel initializer.
  bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);

  /// Returns the AST context.
  ASTContext &getASTContext() const { return Ctx; }
  /// Returns the language options.
  const LangOptions &getLangOpts() const;
  /// Returns the interpreter stack.
  InterpStack &getStack() { return Stk; }
  /// Returns CHAR_BIT.
  unsigned getCharBit() const;
  /// Return the floating-point semantics for T.
  const llvm::fltSemantics &getFloatSemantics(QualType T) const;
  /// Return the size of T in bits.
  uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }

  /// Classifies a type.
  std::optional<PrimType> classify(QualType T) const;

  /// Classifies an expression.
  std::optional<PrimType> classify(const Expr *E) const {
    assert(E);
    if (E->isGLValue()) {
      if (E->getType()->isFunctionType())
        return PT_FnPtr;
      return PT_Ptr;
    }

    return classify(E->getType());
  }

  const CXXMethodDecl *
  getOverridingFunction(const CXXRecordDecl *DynamicDecl,
                        const CXXRecordDecl *StaticDecl,
                        const CXXMethodDecl *InitialFunction) const;

  const Function *getOrCreateFunction(const FunctionDecl *FD);

  /// Returns whether we should create a global variable for the
  /// given ValueDecl.
  static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
    if (const auto *V = dyn_cast<VarDecl>(VD))
      return V->hasGlobalStorage() || V->isConstexpr();

    return false;
  }

  /// Returns the program. This is only needed for unittests.
  Program &getProgram() const { return *P.get(); }

  unsigned collectBaseOffset(const RecordDecl *BaseDecl,
                             const RecordDecl *DerivedDecl) const;

  const Record *getRecord(const RecordDecl *D) const;

  unsigned getEvalID() const { return EvalID; }

private:
  /// Runs a function.
  bool Run(State &Parent, const Function *Func);

  /// Current compilation context.
  ASTContext &Ctx;
  /// Interpreter stack, shared across invocations.
  InterpStack Stk;
  /// Constexpr program.
  std::unique_ptr<Program> P;
  /// ID identifying an evaluation.
  unsigned EvalID = 0;
};

} // namespace interp
} // namespace clang

#endif