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
22namespace clang {
23namespace interp {
24class Context;
25class Function;
26class InterpStack;
27class Program;
28enum Opcode : uint32_t;
29
30/// An emitter which evaluates opcodes as they are emitted.
31class EvalEmitter : public SourceMapper {
32public:
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
46protected:
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{.Offset: 0, .IsPtr: false};
85 /// Local descriptors.
86 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
87
88private:
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(Val: 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
127protected:
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