Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:56

0001 //===--- Interpreter.h - Incremental Compilation and Execution---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the component which performs incremental code
0010 // compilation and execution.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
0015 #define LLVM_CLANG_INTERPRETER_INTERPRETER_H
0016 
0017 #include "clang/AST/GlobalDecl.h"
0018 #include "clang/Interpreter/PartialTranslationUnit.h"
0019 #include "clang/Interpreter/Value.h"
0020 
0021 #include "llvm/ADT/DenseMap.h"
0022 #include "llvm/ExecutionEngine/JITSymbol.h"
0023 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0024 #include "llvm/Support/Error.h"
0025 #include <memory>
0026 #include <vector>
0027 
0028 namespace llvm {
0029 namespace orc {
0030 class LLJIT;
0031 class LLJITBuilder;
0032 class ThreadSafeContext;
0033 } // namespace orc
0034 } // namespace llvm
0035 
0036 namespace clang {
0037 
0038 class CompilerInstance;
0039 class CodeGenerator;
0040 class CXXRecordDecl;
0041 class Decl;
0042 class IncrementalExecutor;
0043 class IncrementalParser;
0044 class IncrementalCUDADeviceParser;
0045 
0046 /// Create a pre-configured \c CompilerInstance for incremental processing.
0047 class IncrementalCompilerBuilder {
0048 public:
0049   IncrementalCompilerBuilder() {}
0050 
0051   void SetCompilerArgs(const std::vector<const char *> &Args) {
0052     UserArgs = Args;
0053   }
0054 
0055   void SetTargetTriple(std::string TT) { TargetTriple = TT; }
0056 
0057   // General C++
0058   llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp();
0059 
0060   // Offload options
0061   void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; };
0062 
0063   // CUDA specific
0064   void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; };
0065 
0066   llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost();
0067   llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice();
0068 
0069 private:
0070   static llvm::Expected<std::unique_ptr<CompilerInstance>>
0071   create(std::string TT, std::vector<const char *> &ClangArgv);
0072 
0073   llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);
0074 
0075   std::vector<const char *> UserArgs;
0076   std::optional<std::string> TargetTriple;
0077 
0078   llvm::StringRef OffloadArch;
0079   llvm::StringRef CudaSDKPath;
0080 };
0081 
0082 class IncrementalAction;
0083 class InProcessPrintingASTConsumer;
0084 
0085 /// Provides top-level interfaces for incremental compilation and execution.
0086 class Interpreter {
0087   friend class Value;
0088   friend InProcessPrintingASTConsumer;
0089 
0090   std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx;
0091   /// Long-lived, incremental parsing action.
0092   std::unique_ptr<IncrementalAction> Act;
0093   std::unique_ptr<IncrementalParser> IncrParser;
0094   std::unique_ptr<IncrementalExecutor> IncrExecutor;
0095 
0096   // An optional parser for CUDA offloading
0097   std::unique_ptr<IncrementalCUDADeviceParser> DeviceParser;
0098 
0099   // An optional action for CUDA offloading
0100   std::unique_ptr<IncrementalAction> DeviceAct;
0101 
0102   /// List containing information about each incrementally parsed piece of code.
0103   std::list<PartialTranslationUnit> PTUs;
0104 
0105   unsigned InitPTUSize = 0;
0106 
0107   // This member holds the last result of the value printing. It's a class
0108   // member because we might want to access it after more inputs. If no value
0109   // printing happens, it's in an invalid state.
0110   Value LastValue;
0111 
0112   /// When CodeGen is created the first llvm::Module gets cached in many places
0113   /// and we must keep it alive.
0114   std::unique_ptr<llvm::Module> CachedInCodeGenModule;
0115 
0116   /// Compiler instance performing the incremental compilation.
0117   std::unique_ptr<CompilerInstance> CI;
0118 
0119   /// An optional compiler instance for CUDA offloading
0120   std::unique_ptr<CompilerInstance> DeviceCI;
0121 
0122 protected:
0123   // Derived classes can use an extended interface of the Interpreter.
0124   Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
0125               std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
0126               std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);
0127 
0128   // Create the internal IncrementalExecutor, or re-create it after calling
0129   // ResetExecutor().
0130   llvm::Error CreateExecutor();
0131 
0132   // Delete the internal IncrementalExecutor. This causes a hard shutdown of the
0133   // JIT engine. In particular, it doesn't run cleanup or destructors.
0134   void ResetExecutor();
0135 
0136 public:
0137   virtual ~Interpreter();
0138   static llvm::Expected<std::unique_ptr<Interpreter>>
0139   create(std::unique_ptr<CompilerInstance> CI);
0140   static llvm::Expected<std::unique_ptr<Interpreter>>
0141   createWithCUDA(std::unique_ptr<CompilerInstance> CI,
0142                  std::unique_ptr<CompilerInstance> DCI);
0143   const ASTContext &getASTContext() const;
0144   ASTContext &getASTContext();
0145   const CompilerInstance *getCompilerInstance() const;
0146   CompilerInstance *getCompilerInstance();
0147   llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine();
0148 
0149   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
0150   llvm::Error Execute(PartialTranslationUnit &T);
0151   llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
0152 
0153   /// Undo N previous incremental inputs.
0154   llvm::Error Undo(unsigned N = 1);
0155 
0156   /// Link a dynamic library
0157   llvm::Error LoadDynamicLibrary(const char *name);
0158 
0159   /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses
0160   /// the CodeGenModule's internal mangling cache to avoid recomputing the
0161   /// mangled name.
0162   llvm::Expected<llvm::orc::ExecutorAddr> getSymbolAddress(GlobalDecl GD) const;
0163 
0164   /// \returns the \c ExecutorAddr of a given name as written in the IR.
0165   llvm::Expected<llvm::orc::ExecutorAddr>
0166   getSymbolAddress(llvm::StringRef IRName) const;
0167 
0168   /// \returns the \c ExecutorAddr of a given name as written in the object
0169   /// file.
0170   llvm::Expected<llvm::orc::ExecutorAddr>
0171   getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
0172 
0173   const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
0174     return ValuePrintingInfo;
0175   }
0176 
0177   Expr *SynthesizeExpr(Expr *E);
0178 
0179 private:
0180   size_t getEffectivePTUSize() const;
0181   void markUserCodeStart();
0182   llvm::Expected<Expr *> ExtractValueFromExpr(Expr *E);
0183   llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
0184 
0185   CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const;
0186   std::unique_ptr<llvm::Module> GenModule(IncrementalAction *Action = nullptr);
0187   PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
0188                                       std::unique_ptr<llvm::Module> M = {},
0189                                       IncrementalAction *Action = nullptr);
0190 
0191   // A cache for the compiled destructors used to for de-allocation of managed
0192   // clang::Values.
0193   llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
0194 
0195   llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
0196 
0197   std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder;
0198 };
0199 } // namespace clang
0200 
0201 #endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H