Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Interpreter/Value.h
Line
Count
Source (jump to first uncovered line)
1
//===--- Value.h - Definition of interpreter value --------------*- 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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Value is a lightweight struct that is used for carrying execution results in
10
// clang-repl. It's a special runtime that acts like a messager between compiled
11
// code and interpreted code. This makes it possible to exchange interesting
12
// information between the compiled & interpreted world.
13
//
14
// A typical usage is like the below:
15
//
16
// Value V;
17
// Interp.ParseAndExecute("int x = 42;");
18
// Interp.ParseAndExecute("x", &V);
19
// V.getType(); // <-- Yields a clang::QualType.
20
// V.getInt(); // <-- Yields 42.
21
//
22
// The current design is still highly experimental and nobody should rely on the
23
// API being stable because we're hopefully going to make significant changes to
24
// it in the relatively near future. For example, Value also intends to be used
25
// as an exchange token for JIT support enabling remote execution on the embed
26
// devices where the JIT infrastructure cannot fit. To support that we will need
27
// to split the memory storage in a different place and perhaps add a resource
28
// header is similar to intrinsics headers which have stricter performance
29
// constraints.
30
//
31
//===----------------------------------------------------------------------===//
32
33
#ifndef LLVM_CLANG_INTERPRETER_VALUE_H
34
#define LLVM_CLANG_INTERPRETER_VALUE_H
35
36
#include "llvm/Support/Compiler.h"
37
#include <cstdint>
38
39
// NOTE: Since the REPL itself could also include this runtime, extreme caution
40
// should be taken when MAKING CHANGES to this file, especially when INCLUDE NEW
41
// HEADERS, like <string>, <memory> and etc. (That pulls a large number of
42
// tokens and will impact the runtime performance of the REPL)
43
44
namespace llvm {
45
class raw_ostream;
46
47
} // namespace llvm
48
49
namespace clang {
50
51
class ASTContext;
52
class Interpreter;
53
class QualType;
54
55
#if defined(_WIN32)
56
// REPL_EXTERNAL_VISIBILITY are symbols that we need to be able to locate
57
// at runtime. On Windows, this requires them to be exported from any of the
58
// modules loaded at runtime. Marking them as dllexport achieves this; both
59
// for DLLs (that normally export symbols as part of their interface) and for
60
// EXEs (that normally don't export anything).
61
// For a build with libclang-cpp.dll, this doesn't make any difference - the
62
// functions would have been exported anyway. But for cases when these are
63
// statically linked into an EXE, it makes sure that they're exported.
64
#define REPL_EXTERNAL_VISIBILITY __declspec(dllexport)
65
#elif __has_attribute(visibility)
66
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
67
#define REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
68
#else
69
#define REPL_EXTERNAL_VISIBILITY
70
#endif
71
#else
72
#define REPL_EXTERNAL_VISIBILITY
73
#endif
74
75
#define REPL_BUILTIN_TYPES                                                     \
76
0
  X(bool, Bool)                                                                \
77
0
  X(char, Char_S)                                                              \
78
0
  X(signed char, SChar)                                                        \
79
0
  X(unsigned char, UChar)                                                      \
80
0
  X(short, Short)                                                              \
81
0
  X(unsigned short, UShort)                                                    \
82
6
  X(int, Int)                                                                  \
83
6
  
X0
(unsigned int, UInt) \
84
0
  X(long, Long)                                                                \
85
0
  X(unsigned long, ULong)                                                      \
86
0
  X(long long, LongLong)                                                       \
87
0
  X(unsigned long long, ULongLong)                                             \
88
0
  X(float, Float)                                                              \
89
1
  X(double, Double)                                                            \
90
1
  
X0
(long double, LongDouble)
91
92
class REPL_EXTERNAL_VISIBILITY Value {
93
  union Storage {
94
#define X(type, name) type m_##name;
95
    REPL_BUILTIN_TYPES
96
#undef X
97
    void *m_Ptr;
98
  };
99
100
public:
101
  enum Kind {
102
#define X(type, name) K_##name,
103
    REPL_BUILTIN_TYPES
104
#undef X
105
106
    K_Void,
107
    K_PtrOrObj,
108
    K_Unspecified
109
  };
110
111
52
  Value() = default;
112
  Value(Interpreter *In, void *Ty);
113
  Value(const Value &RHS);
114
  Value(Value &&RHS) noexcept;
115
  Value &operator=(const Value &RHS);
116
  Value &operator=(Value &&RHS) noexcept;
117
  ~Value();
118
119
  void printType(llvm::raw_ostream &Out) const;
120
  void printData(llvm::raw_ostream &Out) const;
121
  void print(llvm::raw_ostream &Out) const;
122
  void dump() const;
123
  void clear();
124
125
  ASTContext &getASTContext();
126
  const ASTContext &getASTContext() const;
127
  Interpreter &getInterpreter();
128
  const Interpreter &getInterpreter() const;
129
  QualType getType() const;
130
131
317
  bool isValid() const { return ValueKind != K_Unspecified; }
132
  bool isVoid() const { return ValueKind == K_Void; }
133
  bool hasValue() const { return isValid() && !isVoid(); }
134
  bool isManuallyAlloc() const { return IsManuallyAlloc; }
135
  Kind getKind() const { return ValueKind; }
136
9
  void setKind(Kind K) { ValueKind = K; }
137
0
  void setOpaqueType(void *Ty) { OpaqueType = Ty; }
138
139
  void *getPtr() const;
140
4
  void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
141
142
#define X(type, name)                                                          \
143
4
  void set##name(type Val) { Data.m_##name = Val; }                            \
Unexecuted instantiation: clang::Value::setBool(bool)
Unexecuted instantiation: clang::Value::setChar_S(char)
Unexecuted instantiation: clang::Value::setSChar(signed char)
Unexecuted instantiation: clang::Value::setUChar(unsigned char)
Unexecuted instantiation: clang::Value::setShort(short)
Unexecuted instantiation: clang::Value::setUShort(unsigned short)
clang::Value::setInt(int)
Line
Count
Source
143
3
  void set##name(type Val) { Data.m_##name = Val; }                            \
Unexecuted instantiation: clang::Value::setUInt(unsigned int)
Unexecuted instantiation: clang::Value::setLong(long)
Unexecuted instantiation: clang::Value::setULong(unsigned long)
Unexecuted instantiation: clang::Value::setLongLong(long long)
Unexecuted instantiation: clang::Value::setULongLong(unsigned long long)
Unexecuted instantiation: clang::Value::setFloat(float)
clang::Value::setDouble(double)
Line
Count
Source
143
1
  void set##name(type Val) { Data.m_##name = Val; }                            \
Unexecuted instantiation: clang::Value::setLongDouble(long double)
144
0
  type get##name() const { return Data.m_##name; }
Unexecuted instantiation: clang::Value::getBool() const
Unexecuted instantiation: clang::Value::getChar_S() const
Unexecuted instantiation: clang::Value::getSChar() const
Unexecuted instantiation: clang::Value::getUChar() const
Unexecuted instantiation: clang::Value::getShort() const
Unexecuted instantiation: clang::Value::getUShort() const
Unexecuted instantiation: clang::Value::getUInt() const
Unexecuted instantiation: clang::Value::getLong() const
Unexecuted instantiation: clang::Value::getULong() const
Unexecuted instantiation: clang::Value::getLongLong() const
Unexecuted instantiation: clang::Value::getULongLong() const
Unexecuted instantiation: clang::Value::getFloat() const
Unexecuted instantiation: clang::Value::getLongDouble() const
145
  REPL_BUILTIN_TYPES
146
#undef X
147
148
  /// \brief Get the value with cast.
149
  //
150
  /// Get the value cast to T. This is similar to reinterpret_cast<T>(value),
151
  /// casting the value of builtins (except void), enums and pointers.
152
  /// Values referencing an object are treated as pointers to the object.
153
  template <typename T> T convertTo() const {
154
    return convertFwd<T>::cast(*this);
155
  }
156
157
protected:
158
  bool isPointerOrObjectType() const { return ValueKind == K_PtrOrObj; }
159
160
  /// \brief Get to the value with type checking casting the underlying
161
  /// stored value to T.
162
0
  template <typename T> T as() const {
163
0
    switch (ValueKind) {
164
0
    default:
165
0
      return T();
166
0
#define X(type, name)                                                          \
167
0
  case Value::K_##name:                                                        \
168
0
    return (T)Data.m_##name;
169
0
      REPL_BUILTIN_TYPES
170
0
#undef X
171
0
    }
172
0
  }
173
174
  // Allow convertTo to be partially specialized.
175
  template <typename T> struct convertFwd {
176
    static T cast(const Value &V) {
177
      if (V.isPointerOrObjectType())
178
        return (T)(uintptr_t)V.as<void *>();
179
      if (!V.isValid() || V.isVoid()) {
180
        return T();
181
      }
182
      return V.as<T>();
183
    }
184
  };
185
186
  template <typename T> struct convertFwd<T *> {
187
    static T *cast(const Value &V) {
188
      if (V.isPointerOrObjectType())
189
        return (T *)(uintptr_t)V.as<void *>();
190
      return nullptr;
191
    }
192
  };
193
194
  Interpreter *Interp = nullptr;
195
  void *OpaqueType = nullptr;
196
  Storage Data;
197
  Kind ValueKind = K_Unspecified;
198
  bool IsManuallyAlloc = false;
199
};
200
201
0
template <> inline void *Value::as() const {
202
0
  if (isPointerOrObjectType())
203
0
    return Data.m_Ptr;
204
0
  return (void *)as<uintptr_t>();
205
0
}
206
207
} // namespace clang
208
#endif