153 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Defines the instruction emitters.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H14#define LLVM_CLANG_AST_INTERP_EVALEMITTER_H15 16#include "EvaluationResult.h"17#include "InterpState.h"18#include "PrimType.h"19#include "Record.h"20#include "Source.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 using PtrCallback = llvm::function_ref<bool(const Pointer &)>;37 38 EvaluationResult interpretExpr(const Expr *E,39 bool ConvertResultToRValue = false,40 bool DestroyToplevelScope = false);41 EvaluationResult interpretDecl(const VarDecl *VD, const Expr *Init,42 bool CheckFullyInitialized);43 /// Interpret the given Expr to a Pointer.44 EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB);45 /// Interpret the given expression as if it was in the body of the given46 /// function, i.e. the parameters of the function are available for use.47 bool interpretCall(const FunctionDecl *FD, const Expr *E);48 49 /// Clean up all resources.50 void cleanup();51 52protected:53 EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk);54 55 virtual ~EvalEmitter();56 57 /// Define a label.58 void emitLabel(LabelTy Label);59 /// Create a label.60 LabelTy getLabel();61 62 /// Methods implemented by the compiler.63 virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;64 virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,65 bool ConstantContext) = 0;66 virtual bool visitFunc(const FunctionDecl *F) = 0;67 virtual bool visit(const Expr *E) = 0;68 virtual bool emitBool(bool V, const Expr *E) = 0;69 70 /// Emits jumps.71 bool jumpTrue(const LabelTy &Label);72 bool jumpFalse(const LabelTy &Label);73 bool jump(const LabelTy &Label);74 bool fallthrough(const LabelTy &Label);75 /// Speculative execution.76 bool speculate(const CallExpr *E, const LabelTy &EndLabel);77 78 /// Since expressions can only jump forward, predicated execution is79 /// used to deal with if-else statements.80 bool isActive() const { return CurrentLabel == ActiveLabel; }81 bool checkingForUndefinedBehavior() const {82 return S.checkingForUndefinedBehavior();83 }84 85 /// Callback for registering a local.86 Local createLocal(Descriptor *D);87 88 /// Returns the source location of the current opcode.89 SourceInfo getSource(const Function *F, CodePtr PC) const override {90 return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource;91 }92 93 /// Parameter indices.94 llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params;95 /// Lambda captures.96 llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures;97 /// Offset of the This parameter in a lambda record.98 ParamOffset LambdaThisCapture{0, false};99 /// Local descriptors.100 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;101 std::optional<SourceInfo> LocOverride = std::nullopt;102 103private:104 /// Current compilation context.105 Context &Ctx;106 /// Current program.107 Program &P;108 /// Callee evaluation state.109 InterpState S;110 /// Location to write the result to.111 EvaluationResult EvalResult;112 /// Whether the result should be converted to an RValue.113 bool ConvertResultToRValue = false;114 /// Whether we should check if the result has been fully115 /// initialized.116 bool CheckFullyInitialized = false;117 /// Callback to call when using interpretAsPointer.118 std::optional<PtrCallback> PtrCB;119 120 /// Temporaries which require storage.121 llvm::SmallVector<std::unique_ptr<char[]>> Locals;122 123 Block *getLocal(unsigned Index) const {124 assert(Index < Locals.size());125 return reinterpret_cast<Block *>(Locals[Index].get());126 }127 128 void updateGlobalTemporaries();129 130 // The emitter always tracks the current instruction and sets OpPC to a token131 // value which is mapped to the location of the opcode being evaluated.132 CodePtr OpPC;133 /// Location of the current instruction.134 SourceInfo CurrentSource;135 136 /// Next label ID to generate - first label is 1.137 LabelTy NextLabel = 1;138 /// Label being executed - 0 is the entry label.139 LabelTy CurrentLabel = 0;140 /// Active block which should be executed.141 LabelTy ActiveLabel = 0;142 143protected:144#define GET_EVAL_PROTO145#include "Opcodes.inc"146#undef GET_EVAL_PROTO147};148 149} // namespace interp150} // namespace clang151 152#endif153