xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/EvalEmitter.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- EvalEmitter.h - Instruction emitter for the 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the instruction emitters.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
14 #define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
15 
16 #include "EvaluationResult.h"
17 #include "InterpState.h"
18 #include "PrimType.h"
19 #include "Source.h"
20 
21 namespace clang {
22 namespace interp {
23 class Context;
24 class Function;
25 class InterpStack;
26 class Program;
27 enum Opcode : uint32_t;
28 
29 /// An emitter which evaluates opcodes as they are emitted.
30 class EvalEmitter : public SourceMapper {
31 public:
32   using LabelTy = uint32_t;
33   using AddrTy = uintptr_t;
34   using Local = Scope::Local;
35   using PtrCallback = llvm::function_ref<bool(const Pointer &)>;
36 
37   EvaluationResult interpretExpr(const Expr *E,
38                                  bool ConvertResultToRValue = false,
39                                  bool DestroyToplevelScope = false);
40   EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized);
41   /// Interpret the given Expr to a Pointer.
42   EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB);
43 
44   /// Clean up all resources.
45   void cleanup();
46 
47 protected:
48   EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk);
49 
50   virtual ~EvalEmitter();
51 
52   /// Define a label.
53   void emitLabel(LabelTy Label);
54   /// Create a label.
55   LabelTy getLabel();
56 
57   /// Methods implemented by the compiler.
58   virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
59   virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0;
60   virtual bool visitFunc(const FunctionDecl *F) = 0;
61   virtual bool visit(const Expr *E) = 0;
62   virtual bool emitBool(bool V, const Expr *E) = 0;
63 
64   /// Emits jumps.
65   bool jumpTrue(const LabelTy &Label);
66   bool jumpFalse(const LabelTy &Label);
67   bool jump(const LabelTy &Label);
68   bool fallthrough(const LabelTy &Label);
69   /// Speculative execution.
70   bool speculate(const CallExpr *E, const LabelTy &EndLabel);
71 
72   /// Since expressions can only jump forward, predicated execution is
73   /// used to deal with if-else statements.
isActive()74   bool isActive() const { return CurrentLabel == ActiveLabel; }
checkingForUndefinedBehavior()75   bool checkingForUndefinedBehavior() const {
76     return S.checkingForUndefinedBehavior();
77   }
78 
79   /// Callback for registering a local.
80   Local createLocal(Descriptor *D);
81 
82   /// Returns the source location of the current opcode.
getSource(const Function * F,CodePtr PC)83   SourceInfo getSource(const Function *F, CodePtr PC) const override {
84     return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource;
85   }
86 
87   /// Parameter indices.
88   llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params;
89   /// Lambda captures.
90   llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures;
91   /// Offset of the This parameter in a lambda record.
92   ParamOffset LambdaThisCapture{0, false};
93   /// Local descriptors.
94   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
95 
96 private:
97   /// Current compilation context.
98   Context &Ctx;
99   /// Current program.
100   Program &P;
101   /// Callee evaluation state.
102   InterpState S;
103   /// Location to write the result to.
104   EvaluationResult EvalResult;
105   /// Whether the result should be converted to an RValue.
106   bool ConvertResultToRValue = false;
107   /// Whether we should check if the result has been fully
108   /// initialized.
109   bool CheckFullyInitialized = false;
110   /// Callback to call when using interpretAsPointer.
111   std::optional<PtrCallback> PtrCB;
112 
113   /// Temporaries which require storage.
114   llvm::SmallVector<std::unique_ptr<char[]>> Locals;
115 
getLocal(unsigned Index)116   Block *getLocal(unsigned Index) const {
117     assert(Index < Locals.size());
118     return reinterpret_cast<Block *>(Locals[Index].get());
119   }
120 
121   void updateGlobalTemporaries();
122 
123   // The emitter always tracks the current instruction and sets OpPC to a token
124   // value which is mapped to the location of the opcode being evaluated.
125   CodePtr OpPC;
126   /// Location of the current instruction.
127   SourceInfo CurrentSource;
128 
129   /// Next label ID to generate - first label is 1.
130   LabelTy NextLabel = 1;
131   /// Label being executed - 0 is the entry label.
132   LabelTy CurrentLabel = 0;
133   /// Active block which should be executed.
134   LabelTy ActiveLabel = 0;
135 
136 protected:
137 #define GET_EVAL_PROTO
138 #include "Opcodes.inc"
139 #undef GET_EVAL_PROTO
140 };
141 
142 } // namespace interp
143 } // namespace clang
144 
145 #endif
146