forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- EvalEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // Defines the instruction emitters.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
 | |
| #define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
 | |
| 
 | |
| #include "ByteCodeGenError.h"
 | |
| #include "Context.h"
 | |
| #include "InterpStack.h"
 | |
| #include "InterpState.h"
 | |
| #include "PrimType.h"
 | |
| #include "Program.h"
 | |
| #include "Source.h"
 | |
| #include "llvm/Support/Error.h"
 | |
| 
 | |
| namespace clang {
 | |
| class FunctionDecl;
 | |
| namespace interp {
 | |
| class Context;
 | |
| class Function;
 | |
| class InterpState;
 | |
| class Program;
 | |
| class SourceInfo;
 | |
| enum Opcode : uint32_t;
 | |
| 
 | |
| /// An emitter which evaluates opcodes as they are emitted.
 | |
| class EvalEmitter : public SourceMapper {
 | |
| public:
 | |
|   using LabelTy = uint32_t;
 | |
|   using AddrTy = uintptr_t;
 | |
|   using Local = Scope::Local;
 | |
| 
 | |
|   llvm::Expected<bool> interpretExpr(const Expr *E);
 | |
|   llvm::Expected<bool> interpretDecl(const VarDecl *VD);
 | |
| 
 | |
| protected:
 | |
|   EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
 | |
|               APValue &Result);
 | |
| 
 | |
|   virtual ~EvalEmitter() {}
 | |
| 
 | |
|   /// Define a label.
 | |
|   void emitLabel(LabelTy Label);
 | |
|   /// Create a label.
 | |
|   LabelTy getLabel();
 | |
| 
 | |
|   /// Methods implemented by the compiler.
 | |
|   virtual bool visitExpr(const Expr *E) = 0;
 | |
|   virtual bool visitDecl(const VarDecl *VD) = 0;
 | |
| 
 | |
|   bool bail(const Stmt *S) { return bail(S->getBeginLoc()); }
 | |
|   bool bail(const Decl *D) { return bail(D->getBeginLoc()); }
 | |
|   bool bail(const SourceLocation &Loc);
 | |
| 
 | |
|   /// Emits jumps.
 | |
|   bool jumpTrue(const LabelTy &Label);
 | |
|   bool jumpFalse(const LabelTy &Label);
 | |
|   bool jump(const LabelTy &Label);
 | |
|   bool fallthrough(const LabelTy &Label);
 | |
| 
 | |
|   /// Callback for registering a local.
 | |
|   Local createLocal(Descriptor *D);
 | |
| 
 | |
|   /// Returns the source location of the current opcode.
 | |
|   SourceInfo getSource(Function *F, CodePtr PC) const override {
 | |
|     return F ? F->getSource(PC) : CurrentSource;
 | |
|   }
 | |
| 
 | |
|   /// Parameter indices.
 | |
|   llvm::DenseMap<const ParmVarDecl *, unsigned> Params;
 | |
|   /// Local descriptors.
 | |
|   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
 | |
| 
 | |
| private:
 | |
|   /// Current compilation context.
 | |
|   Context &Ctx;
 | |
|   /// Current program.
 | |
|   Program &P;
 | |
|   /// Callee evaluation state.
 | |
|   InterpState S;
 | |
|   /// Location to write the result to.
 | |
|   APValue &Result;
 | |
| 
 | |
|   /// Temporaries which require storage.
 | |
|   llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals;
 | |
| 
 | |
|   // The emitter always tracks the current instruction and sets OpPC to a token
 | |
|   // value which is mapped to the location of the opcode being evaluated.
 | |
|   CodePtr OpPC;
 | |
|   /// Location of a failure.
 | |
|   llvm::Optional<SourceLocation> BailLocation;
 | |
|   /// Location of the current instruction.
 | |
|   SourceInfo CurrentSource;
 | |
| 
 | |
|   /// Next label ID to generate - first label is 1.
 | |
|   LabelTy NextLabel = 1;
 | |
|   /// Label being executed - 0 is the entry label.
 | |
|   LabelTy CurrentLabel = 0;
 | |
|   /// Active block which should be executed.
 | |
|   LabelTy ActiveLabel = 0;
 | |
| 
 | |
|   /// Since expressions can only jump forward, predicated execution is
 | |
|   /// used to deal with if-else statements.
 | |
|   bool isActive() { return CurrentLabel == ActiveLabel; }
 | |
| 
 | |
|   /// Helper to invoke a method.
 | |
|   bool ExecuteCall(Function *F, Pointer &&This, const SourceInfo &Info);
 | |
|   /// Helper to emit a diagnostic on a missing method.
 | |
|   bool ExecuteNoCall(const FunctionDecl *F, const SourceInfo &Info);
 | |
| 
 | |
| protected:
 | |
| #define GET_EVAL_PROTO
 | |
| #include "Opcodes.inc"
 | |
| #undef GET_EVAL_PROTO
 | |
| };
 | |
| 
 | |
| } // namespace interp
 | |
| } // namespace clang
 | |
| 
 | |
| #endif
 |