1 //===--- EvalEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Defines the instruction emitters.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
14 #define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
16 #include "InterpState.h"
19 #include "llvm/Support/Error.h"
27 enum Opcode
: uint32_t;
29 /// An emitter which evaluates opcodes as they are emitted.
30 class EvalEmitter
: public SourceMapper
{
32 using LabelTy
= uint32_t;
33 using AddrTy
= uintptr_t;
34 using Local
= Scope::Local
;
36 llvm::Expected
<bool> interpretExpr(const Expr
*E
);
37 llvm::Expected
<bool> interpretDecl(const VarDecl
*VD
);
40 EvalEmitter(Context
&Ctx
, Program
&P
, State
&Parent
, InterpStack
&Stk
,
43 virtual ~EvalEmitter();
46 void emitLabel(LabelTy Label
);
50 /// Methods implemented by the compiler.
51 virtual bool visitExpr(const Expr
*E
) = 0;
52 virtual bool visitDecl(const VarDecl
*VD
) = 0;
54 bool bail(const Stmt
*S
) { return bail(S
->getBeginLoc()); }
55 bool bail(const Decl
*D
) { return bail(D
->getBeginLoc()); }
56 bool bail(const SourceLocation
&Loc
);
59 bool jumpTrue(const LabelTy
&Label
);
60 bool jumpFalse(const LabelTy
&Label
);
61 bool jump(const LabelTy
&Label
);
62 bool fallthrough(const LabelTy
&Label
);
64 /// Callback for registering a local.
65 Local
createLocal(Descriptor
*D
);
67 /// Returns the source location of the current opcode.
68 SourceInfo
getSource(const Function
*F
, CodePtr PC
) const override
{
69 return (F
&& F
->hasBody()) ? F
->getSource(PC
) : CurrentSource
;
72 /// Parameter indices.
73 llvm::DenseMap
<const ParmVarDecl
*, ParamOffset
> Params
;
75 llvm::DenseMap
<const ValueDecl
*, ParamOffset
> LambdaCaptures
;
76 /// Offset of the This parameter in a lambda record.
77 unsigned LambdaThisCapture
= 0;
78 /// Local descriptors.
79 llvm::SmallVector
<SmallVector
<Local
, 8>, 2> Descriptors
;
82 /// Current compilation context.
86 /// Callee evaluation state.
88 /// Location to write the result to.
91 /// Temporaries which require storage.
92 llvm::DenseMap
<unsigned, std::unique_ptr
<char[]>> Locals
;
94 Block
*getLocal(unsigned Index
) const {
95 auto It
= Locals
.find(Index
);
96 assert(It
!= Locals
.end() && "Missing local variable");
97 return reinterpret_cast<Block
*>(It
->second
.get());
100 // The emitter always tracks the current instruction and sets OpPC to a token
101 // value which is mapped to the location of the opcode being evaluated.
103 /// Location of a failure.
104 std::optional
<SourceLocation
> BailLocation
;
105 /// Location of the current instruction.
106 SourceInfo CurrentSource
;
108 /// Next label ID to generate - first label is 1.
109 LabelTy NextLabel
= 1;
110 /// Label being executed - 0 is the entry label.
111 LabelTy CurrentLabel
= 0;
112 /// Active block which should be executed.
113 LabelTy ActiveLabel
= 0;
115 /// Since expressions can only jump forward, predicated execution is
116 /// used to deal with if-else statements.
117 bool isActive() const { return CurrentLabel
== ActiveLabel
; }
120 #define GET_EVAL_PROTO
121 #include "Opcodes.inc"
122 #undef GET_EVAL_PROTO
125 } // namespace interp