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