Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===--- Value.h - Definition of interpreter value --------------*- 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 // Value is a lightweight struct that is used for carrying execution results in
0010 // clang-repl. It's a special runtime that acts like a messager between compiled
0011 // code and interpreted code. This makes it possible to exchange interesting
0012 // information between the compiled & interpreted world.
0013 //
0014 // A typical usage is like the below:
0015 //
0016 // Value V;
0017 // Interp.ParseAndExecute("int x = 42;");
0018 // Interp.ParseAndExecute("x", &V);
0019 // V.getType(); // <-- Yields a clang::QualType.
0020 // V.getInt(); // <-- Yields 42.
0021 //
0022 // The current design is still highly experimental and nobody should rely on the
0023 // API being stable because we're hopefully going to make significant changes to
0024 // it in the relatively near future. For example, Value also intends to be used
0025 // as an exchange token for JIT support enabling remote execution on the embed
0026 // devices where the JIT infrastructure cannot fit. To support that we will need
0027 // to split the memory storage in a different place and perhaps add a resource
0028 // header is similar to intrinsics headers which have stricter performance
0029 // constraints.
0030 //
0031 //===----------------------------------------------------------------------===//
0032 
0033 #ifndef LLVM_CLANG_INTERPRETER_VALUE_H
0034 #define LLVM_CLANG_INTERPRETER_VALUE_H
0035 
0036 #include "llvm/Config/llvm-config.h" // for LLVM_BUILD_LLVM_DYLIB, LLVM_BUILD_SHARED_LIBS
0037 #include "llvm/Support/Compiler.h"
0038 #include <cstdint>
0039 
0040 // NOTE: Since the REPL itself could also include this runtime, extreme caution
0041 // should be taken when MAKING CHANGES to this file, especially when INCLUDE NEW
0042 // HEADERS, like <string>, <memory> and etc. (That pulls a large number of
0043 // tokens and will impact the runtime performance of the REPL)
0044 
0045 namespace llvm {
0046 class raw_ostream;
0047 
0048 } // namespace llvm
0049 
0050 namespace clang {
0051 
0052 class ASTContext;
0053 class Interpreter;
0054 class QualType;
0055 
0056 #if defined(_WIN32)
0057 // REPL_EXTERNAL_VISIBILITY are symbols that we need to be able to locate
0058 // at runtime. On Windows, this requires them to be exported from any of the
0059 // modules loaded at runtime. Marking them as dllexport achieves this; both
0060 // for DLLs (that normally export symbols as part of their interface) and for
0061 // EXEs (that normally don't export anything).
0062 // For a build with libclang-cpp.dll, this doesn't make any difference - the
0063 // functions would have been exported anyway. But for cases when these are
0064 // statically linked into an EXE, it makes sure that they're exported.
0065 #define REPL_EXTERNAL_VISIBILITY __declspec(dllexport)
0066 #elif __has_attribute(visibility)
0067 #if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
0068 #define REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
0069 #else
0070 #define REPL_EXTERNAL_VISIBILITY
0071 #endif
0072 #else
0073 #define REPL_EXTERNAL_VISIBILITY
0074 #endif
0075 
0076 #define REPL_BUILTIN_TYPES                                                     \
0077   X(bool, Bool)                                                                \
0078   X(char, Char_S)                                                              \
0079   X(signed char, SChar)                                                        \
0080   X(unsigned char, Char_U)                                                     \
0081   X(unsigned char, UChar)                                                      \
0082   X(short, Short)                                                              \
0083   X(unsigned short, UShort)                                                    \
0084   X(int, Int)                                                                  \
0085   X(unsigned int, UInt)                                                        \
0086   X(long, Long)                                                                \
0087   X(unsigned long, ULong)                                                      \
0088   X(long long, LongLong)                                                       \
0089   X(unsigned long long, ULongLong)                                             \
0090   X(float, Float)                                                              \
0091   X(double, Double)                                                            \
0092   X(long double, LongDouble)
0093 
0094 class REPL_EXTERNAL_VISIBILITY Value {
0095   union Storage {
0096 #define X(type, name) type m_##name;
0097     REPL_BUILTIN_TYPES
0098 #undef X
0099     void *m_Ptr;
0100   };
0101 
0102 public:
0103   enum Kind {
0104 #define X(type, name) K_##name,
0105     REPL_BUILTIN_TYPES
0106 #undef X
0107 
0108     K_Void,
0109     K_PtrOrObj,
0110     K_Unspecified
0111   };
0112 
0113   Value() = default;
0114   Value(Interpreter *In, void *Ty);
0115   Value(const Value &RHS);
0116   Value(Value &&RHS) noexcept;
0117   Value &operator=(const Value &RHS);
0118   Value &operator=(Value &&RHS) noexcept;
0119   ~Value();
0120 
0121   void printType(llvm::raw_ostream &Out) const;
0122   void printData(llvm::raw_ostream &Out) const;
0123   void print(llvm::raw_ostream &Out) const;
0124   void dump() const;
0125   void clear();
0126 
0127   ASTContext &getASTContext();
0128   const ASTContext &getASTContext() const;
0129   Interpreter &getInterpreter();
0130   const Interpreter &getInterpreter() const;
0131   QualType getType() const;
0132 
0133   bool isValid() const { return ValueKind != K_Unspecified; }
0134   bool isVoid() const { return ValueKind == K_Void; }
0135   bool hasValue() const { return isValid() && !isVoid(); }
0136   bool isManuallyAlloc() const { return IsManuallyAlloc; }
0137   Kind getKind() const { return ValueKind; }
0138   void setKind(Kind K) { ValueKind = K; }
0139   void setOpaqueType(void *Ty) { OpaqueType = Ty; }
0140 
0141   void *getPtr() const;
0142   void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
0143 
0144 #define X(type, name)                                                          \
0145   void set##name(type Val) { Data.m_##name = Val; }                            \
0146   type get##name() const { return Data.m_##name; }
0147   REPL_BUILTIN_TYPES
0148 #undef X
0149 
0150   /// \brief Get the value with cast.
0151   //
0152   /// Get the value cast to T. This is similar to reinterpret_cast<T>(value),
0153   /// casting the value of builtins (except void), enums and pointers.
0154   /// Values referencing an object are treated as pointers to the object.
0155   template <typename T> T convertTo() const {
0156     return convertFwd<T>::cast(*this);
0157   }
0158 
0159 protected:
0160   bool isPointerOrObjectType() const { return ValueKind == K_PtrOrObj; }
0161 
0162   /// \brief Get to the value with type checking casting the underlying
0163   /// stored value to T.
0164   template <typename T> T as() const {
0165     switch (ValueKind) {
0166     default:
0167       return T();
0168 #define X(type, name)                                                          \
0169   case Value::K_##name:                                                        \
0170     return (T)Data.m_##name;
0171       REPL_BUILTIN_TYPES
0172 #undef X
0173     }
0174   }
0175 
0176   // Allow convertTo to be partially specialized.
0177   template <typename T> struct convertFwd {
0178     static T cast(const Value &V) {
0179       if (V.isPointerOrObjectType())
0180         return (T)(uintptr_t)V.as<void *>();
0181       if (!V.isValid() || V.isVoid()) {
0182         return T();
0183       }
0184       return V.as<T>();
0185     }
0186   };
0187 
0188   template <typename T> struct convertFwd<T *> {
0189     static T *cast(const Value &V) {
0190       if (V.isPointerOrObjectType())
0191         return (T *)(uintptr_t)V.as<void *>();
0192       return nullptr;
0193     }
0194   };
0195 
0196   Interpreter *Interp = nullptr;
0197   void *OpaqueType = nullptr;
0198   Storage Data;
0199   Kind ValueKind = K_Unspecified;
0200   bool IsManuallyAlloc = false;
0201 };
0202 
0203 template <> inline void *Value::as() const {
0204   if (isPointerOrObjectType())
0205     return Data.m_Ptr;
0206   return (void *)as<uintptr_t>();
0207 }
0208 
0209 } // namespace clang
0210 #endif