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
21namespace clang {
22namespace interp {
23class Context;
24class Function;
25class InterpStack;
26class Program;
27enum Opcode : uint32_t;
28
29/// An emitter which evaluates opcodes as they are emitted.
30class EvalEmitter : public SourceMapper {
31public:
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
47protected:
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.
74 bool isActive() const { return CurrentLabel == ActiveLabel; }
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.
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{.Offset: 0, .IsPtr: false};
93 /// Local descriptors.
94 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
95
96private:
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
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
136protected:
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