Coverage Report

Created: 2025-07-23 06:30

/src/WasmEdge/lib/llvm/llvm.h
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
#pragma once
4
5
#if defined(__GNUC__) || defined(__clang__)
6
#pragma GCC diagnostic push
7
#pragma GCC diagnostic ignored "-Wcpp"
8
#include <ciso646>
9
#pragma GCC diagnostic pop
10
#endif
11
12
#include "common/errcode.h"
13
#include "common/span.h"
14
#include <llvm-c/Analysis.h>
15
#include <llvm-c/Core.h>
16
#include <llvm-c/Error.h>
17
#include <llvm-c/Object.h>
18
#include <llvm-c/Orc.h>
19
#include <llvm-c/Target.h>
20
#include <llvm-c/TargetMachine.h>
21
#include <llvm-c/Types.h>
22
#include <mutex>
23
#include <string_view>
24
#include <utility>
25
#include <vector>
26
27
#if LLVM_VERSION_MAJOR >= 12
28
#include <llvm-c/LLJIT.h>
29
#endif
30
31
#if LLVM_VERSION_MAJOR < 12 && WASMEDGE_OS_WINDOWS
32
using LLVMOrcObjectLayerRef = struct LLVMOrcOpaqueObjectLayer *;
33
using LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction =
34
    LLVMOrcObjectLayerRef (*)(void *Ctx, LLVMOrcExecutionSessionRef ES,
35
                              const char *Triple) noexcept;
36
static void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(
37
    LLVMOrcLLJITBuilderRef Builder,
38
    LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, void *Ctx) noexcept;
39
#endif
40
#if LLVM_VERSION_MAJOR < 13
41
using LLVMOrcMaterializationResponsibilityRef =
42
    struct LLVMOrcOpaqueMaterializationResponsibility *;
43
using LLVMOrcIRTransformLayerRef = struct LLVMOrcOpaqueIRTransformLayer *;
44
using LLVMOrcIRTransformLayerTransformFunction =
45
    LLVMErrorRef (*)(void *Ctx, LLVMOrcThreadSafeModuleRef *ModInOut,
46
                     LLVMOrcMaterializationResponsibilityRef MR) noexcept;
47
using LLVMOrcGenericIRModuleOperationFunction =
48
    LLVMErrorRef (*)(void *Ctx, LLVMModuleRef M) noexcept;
49
static LLVMOrcIRTransformLayerRef
50
LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept;
51
static void LLVMOrcIRTransformLayerSetTransform(
52
    LLVMOrcIRTransformLayerRef IRTransformLayer,
53
    LLVMOrcIRTransformLayerTransformFunction TransformFunction,
54
    void *Ctx) noexcept;
55
static LLVMErrorRef
56
LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM,
57
                                    LLVMOrcGenericIRModuleOperationFunction F,
58
                                    void *Ctx) noexcept;
59
#endif
60
61
#if LLVM_VERSION_MAJOR >= 13
62
#include <llvm-c/Transforms/PassBuilder.h>
63
#else
64
#include <llvm-c/Transforms/IPO.h>
65
#include <llvm-c/Transforms/PassManagerBuilder.h>
66
#include <llvm-c/Transforms/Scalar.h>
67
#endif
68
69
// Enable __x86_64__ for MSVC
70
#if defined(_M_X64) && !defined(__x86_64__)
71
#define __x86_64__ 1
72
#endif
73
74
namespace WasmEdge::LLVM {
75
76
class Core {
77
public:
78
1.97k
  static inline void init() noexcept { std::call_once(Once, initOnce); }
79
80
  static inline const unsigned int NotIntrinsic = 0;
81
  static inline unsigned int Ceil = 0;
82
  static inline unsigned int CopySign = 0;
83
  static inline unsigned int Ctlz = 0;
84
  static inline unsigned int Cttz = 0;
85
  static inline unsigned int Ctpop = 0;
86
  static inline unsigned int Expect = 0;
87
  static inline unsigned int ExperimentalConstrainedFAdd = 0;
88
  static inline unsigned int ExperimentalConstrainedFDiv = 0;
89
  static inline unsigned int ExperimentalConstrainedFMul = 0;
90
  static inline unsigned int ExperimentalConstrainedFPExt = 0;
91
  static inline unsigned int ExperimentalConstrainedFPTrunc = 0;
92
  static inline unsigned int ExperimentalConstrainedFSub = 0;
93
  static inline unsigned int Fabs = 0;
94
  static inline unsigned int Floor = 0;
95
  static inline unsigned int FShl = 0;
96
  static inline unsigned int FShr = 0;
97
  static inline unsigned int MaxNum = 0;
98
  static inline unsigned int MinNum = 0;
99
  static inline unsigned int Nearbyint = 0;
100
  static inline unsigned int Roundeven = 0;
101
  static inline unsigned int SAddSat = 0;
102
  static inline unsigned int Sqrt = 0;
103
  static inline unsigned int SSubSat = 0;
104
  static inline unsigned int Trunc = 0;
105
  static inline unsigned int UAddSat = 0;
106
  static inline unsigned int USubSat = 0;
107
#if defined(__x86_64__)
108
  static inline unsigned int X86SSE2PAvgB = 0;
109
  static inline unsigned int X86SSE2PAvgW = 0;
110
  static inline unsigned int X86SSE2PMAddWd = 0;
111
  static inline unsigned int X86SSE41RoundPd = 0;
112
  static inline unsigned int X86SSE41RoundPs = 0;
113
  static inline unsigned int X86SSE41RoundSd = 0;
114
  static inline unsigned int X86SSE41RoundSs = 0;
115
  static inline unsigned int X86SSSE3PMAddUbSw128 = 0;
116
  static inline unsigned int X86SSSE3PMulHrSw128 = 0;
117
  static inline unsigned int X86SSSE3PShufB128 = 0;
118
  static inline unsigned int X86XOpVPHAddBW = 0;
119
  static inline unsigned int X86XOpVPHAddUBW = 0;
120
  static inline unsigned int X86XOpVPHAddUWD = 0;
121
  static inline unsigned int X86XOpVPHAddWD = 0;
122
#endif
123
#if defined(__aarch64__)
124
  static inline unsigned int AArch64NeonFRIntN = 0;
125
  static inline unsigned int AArch64NeonSAddLP = 0;
126
  static inline unsigned int AArch64NeonSQRDMulH = 0;
127
  static inline unsigned int AArch64NeonTbl1 = 0;
128
  static inline unsigned int AArch64NeonUAddLP = 0;
129
  static inline unsigned int AArch64NeonURHAdd = 0;
130
#endif
131
132
  static inline unsigned int Cold = 0;
133
  static inline unsigned int NoAlias = 0;
134
  static inline unsigned int NoInline = 0;
135
  static inline unsigned int NoReturn = 0;
136
  static inline unsigned int ReadOnly = 0;
137
  static inline unsigned int StrictFP = 0;
138
  static inline unsigned int UWTable = 0;
139
#if LLVM_VERSION_MAJOR >= 15
140
  static constexpr inline const unsigned int UWTableDefault = 2;
141
#else
142
  static constexpr inline const unsigned int UWTableDefault = 0;
143
#endif
144
145
  static inline unsigned int InvariantGroup = 0;
146
147
private:
148
  static inline std::once_flag Once;
149
1
  static inline void initOnce() noexcept {
150
1
    using namespace std::literals;
151
1
#if LLVM_VERSION_MAJOR < 17
152
1
    LLVMInitializeCore(LLVMGetGlobalPassRegistry());
153
1
#endif
154
1
    LLVMInitializeNativeTarget();
155
1
    LLVMInitializeNativeAsmPrinter();
156
157
1
    Ceil = getIntrinsicID("llvm.ceil"sv);
158
1
    CopySign = getIntrinsicID("llvm.copysign"sv);
159
1
    Ctlz = getIntrinsicID("llvm.ctlz"sv);
160
1
    Cttz = getIntrinsicID("llvm.cttz"sv);
161
1
    Ctpop = getIntrinsicID("llvm.ctpop"sv);
162
1
    Expect = getIntrinsicID("llvm.expect");
163
1
    ExperimentalConstrainedFAdd =
164
1
        getIntrinsicID("llvm.experimental.constrained.fadd"sv);
165
1
    ExperimentalConstrainedFDiv =
166
1
        getIntrinsicID("llvm.experimental.constrained.fdiv"sv);
167
1
    ExperimentalConstrainedFMul =
168
1
        getIntrinsicID("llvm.experimental.constrained.fmul"sv);
169
1
    ExperimentalConstrainedFPExt =
170
1
        getIntrinsicID("llvm.experimental.constrained.fpext"sv);
171
1
    ExperimentalConstrainedFPTrunc =
172
1
        getIntrinsicID("llvm.experimental.constrained.fptrunc"sv);
173
1
    ExperimentalConstrainedFSub =
174
1
        getIntrinsicID("llvm.experimental.constrained.fsub"sv);
175
1
    Fabs = getIntrinsicID("llvm.fabs"sv);
176
1
    Floor = getIntrinsicID("llvm.floor"sv);
177
1
    FShl = getIntrinsicID("llvm.fshl"sv);
178
1
    FShr = getIntrinsicID("llvm.fshr"sv);
179
1
    MaxNum = getIntrinsicID("llvm.maxnum"sv);
180
1
    MinNum = getIntrinsicID("llvm.minnum"sv);
181
1
    Nearbyint = getIntrinsicID("llvm.nearbyint"sv);
182
1
    Roundeven = getIntrinsicID("llvm.roundeven"sv);
183
1
    SAddSat = getIntrinsicID("llvm.sadd.sat"sv);
184
1
    Sqrt = getIntrinsicID("llvm.sqrt"sv);
185
1
    SSubSat = getIntrinsicID("llvm.ssub.sat"sv);
186
1
    Trunc = getIntrinsicID("llvm.trunc"sv);
187
1
    UAddSat = getIntrinsicID("llvm.uadd.sat"sv);
188
1
    USubSat = getIntrinsicID("llvm.usub.sat"sv);
189
190
1
#if defined(__x86_64__)
191
1
    X86SSE2PAvgB = getIntrinsicID("llvm.x86.sse2.pavg.b"sv);
192
1
    X86SSE2PAvgW = getIntrinsicID("llvm.x86.sse2.pavg.w"sv);
193
1
    X86SSE2PMAddWd = getIntrinsicID("llvm.x86.sse2.pmadd.wd"sv);
194
1
    X86SSE41RoundPd = getIntrinsicID("llvm.x86.sse41.round.pd"sv);
195
1
    X86SSE41RoundPs = getIntrinsicID("llvm.x86.sse41.round.ps"sv);
196
1
    X86SSE41RoundSd = getIntrinsicID("llvm.x86.sse41.round.sd"sv);
197
1
    X86SSE41RoundSs = getIntrinsicID("llvm.x86.sse41.round.ss"sv);
198
1
    X86SSSE3PMAddUbSw128 = getIntrinsicID("llvm.x86.ssse3.pmadd.ub.sw.128"sv);
199
1
    X86SSSE3PMulHrSw128 = getIntrinsicID("llvm.x86.ssse3.pmul.hr.sw.128"sv);
200
1
    X86SSSE3PShufB128 = getIntrinsicID("llvm.x86.ssse3.pshuf.b.128"sv);
201
1
    X86XOpVPHAddBW = getIntrinsicID("llvm.x86.xop.vphaddbw"sv);
202
1
    X86XOpVPHAddUBW = getIntrinsicID("llvm.x86.xop.vphaddubw"sv);
203
1
    X86XOpVPHAddUWD = getIntrinsicID("llvm.x86.xop.vphadduwd"sv);
204
1
    X86XOpVPHAddWD = getIntrinsicID("llvm.x86.xop.vphaddwd"sv);
205
1
#endif
206
#if defined(__aarch64__)
207
    AArch64NeonFRIntN = getIntrinsicID("llvm.aarch64.neon.frintn"sv);
208
    AArch64NeonSAddLP = getIntrinsicID("llvm.aarch64.neon.saddlp"sv);
209
    AArch64NeonSQRDMulH = getIntrinsicID("llvm.aarch64.neon.sqrdmulh"sv);
210
    AArch64NeonTbl1 = getIntrinsicID("llvm.aarch64.neon.tbl1"sv);
211
    AArch64NeonUAddLP = getIntrinsicID("llvm.aarch64.neon.uaddlp"sv);
212
    AArch64NeonURHAdd = getIntrinsicID("llvm.aarch64.neon.urhadd"sv);
213
#endif
214
215
1
    Cold = getEnumAttributeKind("cold"sv);
216
1
    NoAlias = getEnumAttributeKind("noalias"sv);
217
1
    NoInline = getEnumAttributeKind("noinline"sv);
218
1
    NoReturn = getEnumAttributeKind("noreturn"sv);
219
1
    ReadOnly = getEnumAttributeKind("readonly"sv);
220
1
    StrictFP = getEnumAttributeKind("strictfp"sv);
221
1
    UWTable = getEnumAttributeKind("uwtable"sv);
222
223
1
    InvariantGroup = getMetadataKind("invariant.group"sv);
224
1
  }
225
226
  template <typename... ArgsT>
227
  static unsigned int getIntrinsicID(std::string_view Name,
228
40
                                     ArgsT &&...Args) noexcept {
229
40
    const auto Value = LLVMLookupIntrinsicID(Name.data(), Name.size());
230
40
    if constexpr (sizeof...(Args) == 0) {
231
40
      return Value;
232
    } else {
233
      if (Value == NotIntrinsic) {
234
        return getIntrinsicID(std::forward<ArgsT>(Args)...);
235
      }
236
    }
237
40
  }
238
7
  static unsigned int getEnumAttributeKind(std::string_view Name) noexcept {
239
7
    return LLVMGetEnumAttributeKindForName(Name.data(), Name.size());
240
7
  }
241
1
  static unsigned int getMetadataKind(std::string_view Name) noexcept {
242
1
    return LLVMGetMDKindID(Name.data(), static_cast<unsigned int>(Name.size()));
243
1
  }
244
};
245
246
class Attribute;
247
class Message;
248
class Metadata;
249
class PassManager;
250
class Type;
251
class Value;
252
class Builder;
253
class BasicBlock;
254
255
class Context {
256
public:
257
5.91k
  constexpr Context(LLVMContextRef R) noexcept : Ref(R) {}
258
  Context(const Context &) = default;
259
  Context &operator=(const Context &) = default;
260
261
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
262
1.97k
  constexpr auto &unwrap() const noexcept { return Ref; }
263
179k
  constexpr auto &unwrap() noexcept { return Ref; }
264
0
  friend void swap(Context &LHS, Context &RHS) noexcept {
265
0
    using std::swap;
266
0
    swap(LHS.Ref, RHS.Ref);
267
0
  }
268
269
  inline Type getVoidTy() noexcept;
270
  inline Type getInt1Ty() noexcept;
271
  inline Type getInt8Ty() noexcept;
272
  inline Type getInt16Ty() noexcept;
273
  inline Type getInt32Ty() noexcept;
274
  inline Type getInt64Ty() noexcept;
275
  inline Type getInt128Ty() noexcept;
276
  inline Type getIntNTy(unsigned int NumBits) noexcept;
277
  inline Type getFloatTy() noexcept;
278
  inline Type getDoubleTy() noexcept;
279
280
  inline Value getFalse() noexcept;
281
  inline Value getTrue() noexcept;
282
  inline Value getInt8(uint8_t C) noexcept;
283
  inline Value getInt16(uint16_t C) noexcept;
284
  inline Value getInt32(uint32_t C) noexcept;
285
  inline Value getInt64(uint64_t C) noexcept;
286
  inline Value getFloat(float C) noexcept;
287
  inline Value getDouble(double C) noexcept;
288
289
private:
290
  LLVMContextRef Ref = nullptr;
291
};
292
293
class Module {
294
public:
295
  constexpr Module() noexcept = default;
296
0
  constexpr Module(LLVMModuleRef R) noexcept : Ref(R) {}
297
  Module(const Module &) = delete;
298
  Module &operator=(const Module &) = delete;
299
0
  Module(Module &&M) noexcept : Module() { swap(*this, M); }
300
0
  Module &operator=(Module &&M) noexcept {
301
0
    swap(*this, M);
302
0
    return *this;
303
0
  }
304
305
  Module(const Context &C, const char *Name) noexcept
306
1.97k
      : Ref(LLVMModuleCreateWithNameInContext(Name, C.unwrap())) {}
307
1.97k
  ~Module() noexcept { LLVMDisposeModule(Ref); }
308
309
1.97k
  const char *getTarget() noexcept { return LLVMGetTarget(Ref); }
310
1.97k
  void setTarget(const char *Triple) noexcept { LLVMSetTarget(Ref, Triple); }
311
  inline Value addFunction(Type Ty, LLVMLinkage Linkage,
312
                           const char *Name = "") noexcept;
313
  inline Value addGlobal(Type Ty, bool IsConstant, LLVMLinkage Linkage,
314
                         Value Initializer, const char *Name = "") noexcept;
315
  inline Value getNamedGlobal(const char *Name) noexcept;
316
  inline Value addAlias(Type Ty, Value V, const char *Name,
317
                        unsigned int AddrSpace = 0) noexcept;
318
  inline void addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
319
                      const Metadata &Val) noexcept;
320
  inline void addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
321
                      const Value &Val) noexcept;
322
  inline void addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
323
                      uint32_t Val) noexcept;
324
  inline Value getFirstGlobal() noexcept;
325
  inline Value getFirstFunction() noexcept;
326
  inline Value getNamedFunction(const char *Name) noexcept;
327
  inline Message printModuleToFile(const char *File) noexcept;
328
  inline Message verify(LLVMVerifierFailureAction Action) noexcept;
329
330
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
331
0
  constexpr auto &unwrap() const noexcept { return Ref; }
332
5.91k
  constexpr auto &unwrap() noexcept { return Ref; }
333
0
  LLVMModuleRef release() noexcept { return std::exchange(Ref, nullptr); }
334
0
  friend void swap(Module &LHS, Module &RHS) noexcept {
335
0
    using std::swap;
336
0
    swap(LHS.Ref, RHS.Ref);
337
0
  }
338
339
private:
340
  LLVMModuleRef Ref = nullptr;
341
};
342
343
class ErrorMessage {
344
public:
345
  constexpr ErrorMessage() noexcept = default;
346
0
  constexpr ErrorMessage(char *M) noexcept : Data(M) {}
347
  ErrorMessage(const ErrorMessage &) = delete;
348
  ErrorMessage &operator=(const ErrorMessage &) = delete;
349
0
  ErrorMessage(ErrorMessage &&M) noexcept : ErrorMessage() { swap(*this, M); }
350
0
  ErrorMessage &operator=(ErrorMessage &&M) noexcept {
351
0
    swap(*this, M);
352
0
    return *this;
353
0
  }
354
355
0
  ~ErrorMessage() noexcept { LLVMDisposeErrorMessage(Data); }
356
357
0
  constexpr operator bool() const noexcept { return Data != nullptr; }
358
0
  constexpr auto &unwrap() const noexcept { return Data; }
359
0
  constexpr auto &unwrap() noexcept { return Data; }
360
0
  friend void swap(ErrorMessage &LHS, ErrorMessage &RHS) noexcept {
361
0
    using std::swap;
362
0
    swap(LHS.Data, RHS.Data);
363
0
  }
364
365
0
  std::string_view string_view() const noexcept { return Data; }
366
367
private:
368
  char *Data = nullptr;
369
};
370
371
class Error {
372
public:
373
  constexpr Error() noexcept = default;
374
0
  constexpr Error(LLVMErrorRef R) noexcept : Ref(R) {}
375
  Error(const Error &) = delete;
376
  Error &operator=(const Error &) = delete;
377
0
  Error(Error &&E) noexcept : Error() { swap(*this, E); }
378
0
  Error &operator=(Error &&E) noexcept {
379
0
    swap(*this, E);
380
0
    return *this;
381
0
  }
382
383
0
  ~Error() noexcept { LLVMConsumeError(Ref); }
384
385
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
386
0
  constexpr auto &unwrap() const noexcept { return Ref; }
387
0
  constexpr auto &unwrap() noexcept { return Ref; }
388
0
  LLVMErrorRef release() noexcept { return std::exchange(Ref, nullptr); }
389
0
  friend void swap(Error &LHS, Error &RHS) noexcept {
390
0
    using std::swap;
391
0
    swap(LHS.Ref, RHS.Ref);
392
0
  }
393
394
0
  ErrorMessage message() noexcept {
395
0
    return LLVMGetErrorMessage(std::exchange(Ref, nullptr));
396
0
  }
397
398
private:
399
  LLVMErrorRef Ref = nullptr;
400
};
401
402
class Message {
403
public:
404
11.8k
  constexpr Message() noexcept = default;
405
7.88k
  constexpr Message(char *M) noexcept : Data(M) {}
406
  Message(const Message &) = delete;
407
  Message &operator=(const Message &) = delete;
408
0
  Message(Message &&M) noexcept : Message() { swap(*this, M); }
409
1.97k
  Message &operator=(Message &&M) noexcept {
410
1.97k
    swap(*this, M);
411
1.97k
    return *this;
412
1.97k
  }
413
414
19.7k
  ~Message() noexcept { LLVMDisposeMessage(Data); }
415
416
7.88k
  constexpr operator bool() const noexcept { return Data != nullptr; }
417
0
  constexpr auto &unwrap() const noexcept { return Data; }
418
13.8k
  constexpr auto &unwrap() noexcept { return Data; }
419
1.97k
  friend void swap(Message &LHS, Message &RHS) noexcept {
420
1.97k
    using std::swap;
421
1.97k
    swap(LHS.Data, RHS.Data);
422
1.97k
  }
423
424
3.94k
  std::string_view string_view() const noexcept { return Data; }
425
426
private:
427
  char *Data = nullptr;
428
};
429
430
class MemoryBuffer {
431
public:
432
5.91k
  constexpr MemoryBuffer() noexcept = default;
433
0
  constexpr MemoryBuffer(LLVMMemoryBufferRef R) noexcept : Ref(R) {}
434
  MemoryBuffer(const MemoryBuffer &) = delete;
435
  MemoryBuffer &operator=(const MemoryBuffer &) = delete;
436
0
  MemoryBuffer(MemoryBuffer &&M) noexcept : MemoryBuffer() { swap(*this, M); }
437
1.97k
  MemoryBuffer &operator=(MemoryBuffer &&M) noexcept {
438
1.97k
    swap(*this, M);
439
1.97k
    return *this;
440
1.97k
  }
441
442
5.91k
  ~MemoryBuffer() noexcept { LLVMDisposeMemoryBuffer(Ref); }
443
444
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
445
0
  constexpr auto &unwrap() const noexcept { return Ref; }
446
5.91k
  constexpr auto &unwrap() noexcept { return Ref; }
447
1.97k
  friend void swap(MemoryBuffer &LHS, MemoryBuffer &RHS) noexcept {
448
1.97k
    using std::swap;
449
1.97k
    swap(LHS.Ref, RHS.Ref);
450
1.97k
  }
451
452
1.97k
  static std::pair<MemoryBuffer, Message> getFile(const char *Path) noexcept {
453
1.97k
    std::pair<MemoryBuffer, Message> Result;
454
1.97k
    LLVMCreateMemoryBufferWithContentsOfFile(Path, &Result.first.unwrap(),
455
1.97k
                                             &Result.second.unwrap());
456
1.97k
    return Result;
457
1.97k
  }
458
3.94k
  const char *data() const noexcept { return LLVMGetBufferStart(Ref); }
459
3.94k
  size_t size() const noexcept { return LLVMGetBufferSize(Ref); }
460
461
private:
462
  LLVMMemoryBufferRef Ref = nullptr;
463
};
464
465
class Type {
466
public:
467
4.11M
  constexpr Type() = default;
468
11.1M
  constexpr Type(LLVMTypeRef R) noexcept : Ref(R) {}
469
  constexpr Type(const Type &) = default;
470
  constexpr Type &operator=(const Type &) = default;
471
4.00M
  Type(Type &&T) noexcept : Type() { swap(*this, T); }
472
97.4k
  Type &operator=(Type &&T) noexcept {
473
97.4k
    swap(*this, T);
474
97.4k
    return *this;
475
97.4k
  }
476
477
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
478
0
  constexpr auto &unwrap() const noexcept { return Ref; }
479
11.7M
  constexpr auto &unwrap() noexcept { return Ref; }
480
4.10M
  friend void swap(Type &LHS, Type &RHS) noexcept {
481
4.10M
    using std::swap;
482
4.10M
    swap(LHS.Ref, RHS.Ref);
483
4.10M
  }
484
485
  static Type getFunctionType(Type ReturnType, Span<const Type> ParamTypes,
486
25.1k
                              bool IsVarArg = false) noexcept {
487
25.1k
    const auto Data = const_cast<LLVMTypeRef *>(
488
25.1k
        reinterpret_cast<const LLVMTypeRef *>(ParamTypes.data()));
489
25.1k
    const auto Size = static_cast<unsigned int>(ParamTypes.size());
490
25.1k
    return LLVMFunctionType(ReturnType.unwrap(), Data, Size, IsVarArg);
491
25.1k
  }
492
  static Type getPointerType(Type ElementType,
493
0
                             unsigned int AddressSpace = 0) noexcept {
494
0
    return LLVMPointerType(ElementType.unwrap(), AddressSpace);
495
0
  }
496
  static Type getArrayType(Type ElementType,
497
4.78k
                           unsigned int ElementCount) noexcept {
498
4.78k
    return LLVMArrayType(ElementType.unwrap(), ElementCount);
499
4.78k
  }
500
  static Type getVectorType(Type ElementType,
501
3.50M
                            unsigned int ElementCount) noexcept {
502
3.50M
    return LLVMVectorType(ElementType.unwrap(), ElementCount);
503
3.50M
  }
504
  static Type getStructType(Span<const Type> ElementTypes,
505
599
                            bool Packed = false) noexcept {
506
599
    const auto Data = const_cast<LLVMTypeRef *>(
507
599
        reinterpret_cast<const LLVMTypeRef *>(ElementTypes.data()));
508
599
    const auto Size = static_cast<unsigned int>(ElementTypes.size());
509
599
    assuming(Size >= 1);
510
599
    return LLVMStructTypeInContext(LLVMGetTypeContext(Data[0]), Data, Size,
511
599
                                   Packed);
512
599
  }
513
  static Type getStructType(const char *Name, Span<const Type> ElementTypes,
514
1.97k
                            bool Packed = false) noexcept {
515
1.97k
    const auto Data = const_cast<LLVMTypeRef *>(
516
1.97k
        reinterpret_cast<const LLVMTypeRef *>(ElementTypes.data()));
517
1.97k
    const auto Size = static_cast<unsigned int>(ElementTypes.size());
518
1.97k
    assuming(Size >= 1);
519
1.97k
    Type Ty = LLVMStructCreateNamed(LLVMGetTypeContext(Data[0]), Name);
520
1.97k
    LLVMStructSetBody(Ty.unwrap(), Data, Size, Packed);
521
1.97k
    return Ty;
522
1.97k
  }
523
524
19.2k
  bool isVoidTy() const noexcept {
525
19.2k
    return LLVMGetTypeKind(Ref) == LLVMVoidTypeKind;
526
19.2k
  }
527
44.0k
  bool isFloatTy() const noexcept {
528
44.0k
    return LLVMGetTypeKind(Ref) == LLVMFloatTypeKind;
529
44.0k
  }
530
18.8k
  bool isDoubleTy() const noexcept {
531
18.8k
    return LLVMGetTypeKind(Ref) == LLVMDoubleTypeKind;
532
18.8k
  }
533
3.47k
  bool isIntegerTy() const noexcept {
534
3.47k
    return LLVMGetTypeKind(Ref) == LLVMIntegerTypeKind;
535
3.47k
  }
536
13.3k
  bool isStructTy() const noexcept {
537
13.3k
    return LLVMGetTypeKind(Ref) == LLVMStructTypeKind;
538
13.3k
  }
539
0
  bool isVectorTy() const noexcept {
540
0
    return LLVMGetTypeKind(Ref) == LLVMVectorTypeKind;
541
0
  }
542
543
3.47k
  unsigned int getPrimitiveSizeInBits() const noexcept {
544
3.47k
    switch (LLVMGetTypeKind(Ref)) {
545
0
    case LLVMBFloatTypeKind:
546
0
      return 16;
547
0
    case LLVMHalfTypeKind:
548
0
      return 16;
549
0
    case LLVMFloatTypeKind:
550
0
      return 32;
551
0
    case LLVMDoubleTypeKind:
552
0
      return 64;
553
0
    case LLVMX86_FP80TypeKind:
554
0
      return 80;
555
0
    case LLVMFP128TypeKind:
556
0
      return 128;
557
0
    case LLVMPPC_FP128TypeKind:
558
0
      return 128;
559
0
#if LLVM_VERSION_MAJOR < 20
560
0
    case LLVMX86_MMXTypeKind:
561
0
      return 64;
562
0
#endif
563
3.47k
    case LLVMIntegerTypeKind:
564
3.47k
      return getIntegerBitWidth();
565
0
    case LLVMVectorTypeKind:
566
0
      return getElementType().getPrimitiveSizeInBits() * getVectorSize();
567
0
    default:
568
0
      return 0;
569
3.47k
    }
570
3.47k
  }
571
7.24k
  unsigned int getFPMantissaWidth() const noexcept {
572
7.24k
    switch (LLVMGetTypeKind(Ref)) {
573
0
    case LLVMBFloatTypeKind:
574
0
      return 8;
575
0
    case LLVMHalfTypeKind:
576
0
      return 11;
577
3.18k
    case LLVMFloatTypeKind:
578
3.18k
      return 24;
579
4.06k
    case LLVMDoubleTypeKind:
580
4.06k
      return 53;
581
0
    case LLVMX86_FP80TypeKind:
582
0
      return 64;
583
0
    case LLVMFP128TypeKind:
584
0
      return 113;
585
0
    default:
586
0
      return 0;
587
7.24k
    }
588
7.24k
  }
589
590
74.7k
  Type getElementType() const noexcept { return LLVMGetElementType(Ref); }
591
28.8k
  unsigned int getIntegerBitWidth() const noexcept {
592
28.8k
    return LLVMGetIntTypeWidth(Ref);
593
28.8k
  }
594
9.69k
  Type getIntegerExtendedType() const noexcept {
595
9.69k
    return LLVMIntTypeInContext(LLVMGetTypeContext(Ref),
596
9.69k
                                getIntegerBitWidth() * 2);
597
9.69k
  }
598
639
  Type getIntegerTruncatedType() const noexcept {
599
639
    return LLVMIntTypeInContext(LLVMGetTypeContext(Ref),
600
639
                                getIntegerBitWidth() / 2);
601
639
  }
602
671
  unsigned int getStructNumElements() const noexcept {
603
671
    return LLVMCountStructElementTypes(Ref);
604
671
  }
605
92
  Type getStructElementType(unsigned int Index) const noexcept {
606
92
    return LLVMStructGetTypeAtIndex(Ref, Index);
607
92
  }
608
68.0k
  Type getPointerTo(unsigned int AddressSpace = 0) const noexcept {
609
68.0k
    return LLVMPointerType(Ref, AddressSpace);
610
68.0k
  }
611
15.8k
  Type getReturnType() const noexcept { return LLVMGetReturnType(Ref); }
612
7.52k
  unsigned int getNumParams() const noexcept {
613
7.52k
    return LLVMCountParamTypes(Ref);
614
7.52k
  }
615
3.76k
  void getParamTypes(Span<Type> Types) const noexcept {
616
3.76k
    LLVMGetParamTypes(Ref, reinterpret_cast<LLVMTypeRef *>(Types.data()));
617
3.76k
  }
618
79.6k
  unsigned int getVectorSize() const noexcept { return LLVMGetVectorSize(Ref); }
619
9.69k
  Type getExtendedElementVectorType() const noexcept {
620
9.69k
    return getVectorType(getElementType().getIntegerExtendedType(),
621
9.69k
                         getVectorSize());
622
9.69k
  }
623
639
  Type getTruncatedElementVectorType() const noexcept {
624
639
    return getVectorType(getElementType().getIntegerTruncatedType(),
625
639
                         getVectorSize());
626
639
  }
627
2.05k
  Type getHalfElementsVectorType() const noexcept {
628
2.05k
    return getVectorType(getElementType(), getVectorSize() / 2);
629
2.05k
  }
630
631
private:
632
  LLVMTypeRef Ref = nullptr;
633
};
634
635
class Value {
636
public:
637
4.91M
  constexpr Value() = default;
638
12.0M
  constexpr Value(LLVMValueRef R) noexcept : Ref(R) {}
639
  constexpr Value(const Value &) = default;
640
  constexpr Value &operator=(const Value &) = default;
641
4.78M
  Value(Value &&V) noexcept : Value() { swap(*this, V); }
642
383k
  Value &operator=(Value &&V) noexcept {
643
383k
    swap(*this, V);
644
383k
    return *this;
645
383k
  }
646
647
2.90M
  constexpr operator bool() const noexcept { return Ref != nullptr; }
648
0
  constexpr auto &unwrap() const noexcept { return Ref; }
649
8.35M
  constexpr auto &unwrap() noexcept { return Ref; }
650
651
5.16M
  friend void swap(Value &LHS, Value &RHS) noexcept {
652
5.16M
    using std::swap;
653
5.16M
    swap(LHS.Ref, RHS.Ref);
654
5.16M
  }
655
656
3.12M
  static Value getConstNull(Type Ty) noexcept {
657
3.12M
    return LLVMConstNull(Ty.unwrap());
658
3.12M
  }
659
62
  static Value getConstAllOnes(Type Ty) noexcept {
660
62
    return LLVMConstAllOnes(Ty.unwrap());
661
62
  }
662
94.5k
  static Value getUndef(Type Ty) noexcept { return LLVMGetUndef(Ty.unwrap()); }
663
748
  static Value getConstPointerNull(Type Ty) noexcept {
664
748
    return LLVMConstPointerNull(Ty.unwrap());
665
748
  }
666
  static Value getConstInt(Type IntTy, unsigned long long N,
667
1.03M
                           bool SignExtend = false) noexcept {
668
1.03M
    return LLVMConstInt(IntTy.unwrap(), N, SignExtend);
669
1.03M
  }
670
36.7k
  template <typename T> static Value getConstReal(Type Ty, T N) noexcept {
671
36.7k
    if (Ty.isFloatTy()) {
672
22.0k
      const auto V = static_cast<float>(N);
673
22.0k
      uint32_t Raw;
674
22.0k
      static_assert(sizeof(V) == sizeof(Raw));
675
22.0k
      std::memcpy(&Raw, &V, sizeof(V));
676
22.0k
      Type Int32Ty = LLVMInt32TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
677
22.0k
      Value Ret = getConstInt(Int32Ty, Raw);
678
22.0k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
679
22.0k
    }
680
14.7k
    if (Ty.isDoubleTy()) {
681
14.7k
      const auto V = static_cast<double>(N);
682
14.7k
      uint64_t Raw;
683
14.7k
      static_assert(sizeof(V) == sizeof(Raw));
684
14.7k
      std::memcpy(&Raw, &V, sizeof(V));
685
14.7k
      Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
686
14.7k
      Value Ret = getConstInt(Int64Ty, Raw);
687
14.7k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
688
14.7k
    }
689
14.7k
    assumingUnreachable();
690
14.7k
  }
WasmEdge::LLVM::Value WasmEdge::LLVM::Value::getConstReal<float>(WasmEdge::LLVM::Type, float)
Line
Count
Source
670
15.6k
  template <typename T> static Value getConstReal(Type Ty, T N) noexcept {
671
15.6k
    if (Ty.isFloatTy()) {
672
15.6k
      const auto V = static_cast<float>(N);
673
15.6k
      uint32_t Raw;
674
15.6k
      static_assert(sizeof(V) == sizeof(Raw));
675
15.6k
      std::memcpy(&Raw, &V, sizeof(V));
676
15.6k
      Type Int32Ty = LLVMInt32TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
677
15.6k
      Value Ret = getConstInt(Int32Ty, Raw);
678
15.6k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
679
15.6k
    }
680
0
    if (Ty.isDoubleTy()) {
681
0
      const auto V = static_cast<double>(N);
682
0
      uint64_t Raw;
683
0
      static_assert(sizeof(V) == sizeof(Raw));
684
0
      std::memcpy(&Raw, &V, sizeof(V));
685
0
      Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
686
0
      Value Ret = getConstInt(Int64Ty, Raw);
687
0
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
688
0
    }
689
0
    assumingUnreachable();
690
0
  }
WasmEdge::LLVM::Value WasmEdge::LLVM::Value::getConstReal<double>(WasmEdge::LLVM::Type, double)
Line
Count
Source
670
6.62k
  template <typename T> static Value getConstReal(Type Ty, T N) noexcept {
671
6.62k
    if (Ty.isFloatTy()) {
672
0
      const auto V = static_cast<float>(N);
673
0
      uint32_t Raw;
674
0
      static_assert(sizeof(V) == sizeof(Raw));
675
0
      std::memcpy(&Raw, &V, sizeof(V));
676
0
      Type Int32Ty = LLVMInt32TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
677
0
      Value Ret = getConstInt(Int32Ty, Raw);
678
0
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
679
0
    }
680
6.62k
    if (Ty.isDoubleTy()) {
681
6.62k
      const auto V = static_cast<double>(N);
682
6.62k
      uint64_t Raw;
683
6.62k
      static_assert(sizeof(V) == sizeof(Raw));
684
6.62k
      std::memcpy(&Raw, &V, sizeof(V));
685
6.62k
      Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
686
6.62k
      Value Ret = getConstInt(Int64Ty, Raw);
687
6.62k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
688
6.62k
    }
689
0
    assumingUnreachable();
690
6.62k
  }
WasmEdge::LLVM::Value WasmEdge::LLVM::Value::getConstReal<long>(WasmEdge::LLVM::Type, long)
Line
Count
Source
670
6.05k
  template <typename T> static Value getConstReal(Type Ty, T N) noexcept {
671
6.05k
    if (Ty.isFloatTy()) {
672
3.54k
      const auto V = static_cast<float>(N);
673
3.54k
      uint32_t Raw;
674
3.54k
      static_assert(sizeof(V) == sizeof(Raw));
675
3.54k
      std::memcpy(&Raw, &V, sizeof(V));
676
3.54k
      Type Int32Ty = LLVMInt32TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
677
3.54k
      Value Ret = getConstInt(Int32Ty, Raw);
678
3.54k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
679
3.54k
    }
680
2.50k
    if (Ty.isDoubleTy()) {
681
2.50k
      const auto V = static_cast<double>(N);
682
2.50k
      uint64_t Raw;
683
2.50k
      static_assert(sizeof(V) == sizeof(Raw));
684
2.50k
      std::memcpy(&Raw, &V, sizeof(V));
685
2.50k
      Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
686
2.50k
      Value Ret = getConstInt(Int64Ty, Raw);
687
2.50k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
688
2.50k
    }
689
0
    assumingUnreachable();
690
2.50k
  }
WasmEdge::LLVM::Value WasmEdge::LLVM::Value::getConstReal<unsigned long>(WasmEdge::LLVM::Type, unsigned long)
Line
Count
Source
670
8.43k
  template <typename T> static Value getConstReal(Type Ty, T N) noexcept {
671
8.43k
    if (Ty.isFloatTy()) {
672
2.81k
      const auto V = static_cast<float>(N);
673
2.81k
      uint32_t Raw;
674
2.81k
      static_assert(sizeof(V) == sizeof(Raw));
675
2.81k
      std::memcpy(&Raw, &V, sizeof(V));
676
2.81k
      Type Int32Ty = LLVMInt32TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
677
2.81k
      Value Ret = getConstInt(Int32Ty, Raw);
678
2.81k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
679
2.81k
    }
680
5.61k
    if (Ty.isDoubleTy()) {
681
5.61k
      const auto V = static_cast<double>(N);
682
5.61k
      uint64_t Raw;
683
5.61k
      static_assert(sizeof(V) == sizeof(Raw));
684
5.61k
      std::memcpy(&Raw, &V, sizeof(V));
685
5.61k
      Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
686
5.61k
      Value Ret = getConstInt(Int64Ty, Raw);
687
5.61k
      return LLVMConstBitCast(Ret.unwrap(), Ty.unwrap());
688
5.61k
    }
689
0
    assumingUnreachable();
690
5.61k
  }
691
  static Value getConstString(Context &C, std::string_view Str,
692
0
                              bool DontNullTerminate) noexcept {
693
0
    return LLVMConstStringInContext(C.unwrap(), Str.data(),
694
0
                                    static_cast<unsigned int>(Str.size()),
695
0
                                    DontNullTerminate);
696
0
  }
697
  static Value getConstInBoundsGEP(Type Ty, Value ConstantVal,
698
0
                                   Span<const Value> ConstantIndices) noexcept {
699
0
    const auto Data = const_cast<LLVMValueRef *>(
700
0
        reinterpret_cast<const LLVMValueRef *>(ConstantIndices.data()));
701
0
    const auto Size = static_cast<unsigned int>(ConstantIndices.size());
702
0
    return LLVMConstInBoundsGEP2(Ty.unwrap(), ConstantVal.unwrap(), Data, Size);
703
0
  }
704
  static Value getConstInBoundsGEP1_64(Type Ty, Value ConstantVal,
705
0
                                       uint64_t Idx0) noexcept {
706
0
    return getConstInBoundsGEP(
707
0
        Ty, ConstantVal,
708
0
        {LLVM::Value::getConstInt(
709
0
            LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap())), Idx0)});
710
0
  }
711
  static Value getConstInBoundsGEP2_64(Type Ty, Value ConstantVal,
712
0
                                       uint64_t Idx0, uint64_t Idx1) noexcept {
713
0
    return getConstInBoundsGEP(
714
0
        Ty, ConstantVal,
715
0
        {LLVM::Value::getConstInt(
716
0
            LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap())), Idx0,
717
0
            Idx1)});
718
0
  }
719
35.4k
  static Value getConstVector(Span<const Value> ScalarConstantVals) noexcept {
720
35.4k
    const auto Data = const_cast<LLVMValueRef *>(
721
35.4k
        reinterpret_cast<const LLVMValueRef *>(ScalarConstantVals.data()));
722
35.4k
    const auto Size = static_cast<unsigned int>(ScalarConstantVals.size());
723
35.4k
    return LLVMConstVector(Data, Size);
724
35.4k
  }
725
  static Value getConstVector8(Context &C,
726
1.09k
                               Span<const uint8_t> Elements) noexcept {
727
1.09k
    std::vector<LLVMValueRef> Data(Elements.size());
728
1.09k
    std::transform(
729
1.09k
        Elements.begin(), Elements.end(), Data.begin(),
730
17.4k
        [&C](const uint8_t Element) { return C.getInt8(Element).unwrap(); });
731
1.09k
    return LLVMConstVector(Data.data(), static_cast<unsigned int>(Data.size()));
732
1.09k
  }
733
  static Value getConstVector16(Context &C,
734
0
                                Span<const uint16_t> Elements) noexcept {
735
0
    std::vector<LLVMValueRef> Data(Elements.size());
736
0
    std::transform(
737
0
        Elements.begin(), Elements.end(), Data.begin(),
738
0
        [&C](const uint16_t Element) { return C.getInt16(Element).unwrap(); });
739
0
    return LLVMConstVector(Data.data(), static_cast<unsigned int>(Data.size()));
740
0
  }
741
  static Value getConstVector32(Context &C,
742
15.4k
                                Span<const uint32_t> Elements) noexcept {
743
15.4k
    std::vector<LLVMValueRef> Data(Elements.size());
744
15.4k
    std::transform(
745
15.4k
        Elements.begin(), Elements.end(), Data.begin(),
746
68.9k
        [&C](const uint32_t Element) { return C.getInt32(Element).unwrap(); });
747
15.4k
    return LLVMConstVector(Data.data(), static_cast<unsigned int>(Data.size()));
748
15.4k
  }
749
  static Value getConstVector64(Context &C,
750
368
                                Span<const uint64_t> Elements) noexcept {
751
368
    std::vector<LLVMValueRef> Data(Elements.size());
752
368
    std::transform(
753
368
        Elements.begin(), Elements.end(), Data.begin(),
754
736
        [&C](const uint64_t Element) { return C.getInt64(Element).unwrap(); });
755
368
    return LLVMConstVector(Data.data(), static_cast<unsigned int>(Data.size()));
756
368
  }
757
758
#define DECLARE_VALUE_CHECK(name)                                              \
759
0
  bool isA##name() const noexcept { return LLVMIsA##name(Ref) != nullptr; }
Unexecuted instantiation: WasmEdge::LLVM::Value::isAArgument() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isABasicBlock() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAInlineAsm() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUser() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstant() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isABlockAddress() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantAggregateZero() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantArray() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantDataSequential() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantDataArray() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantDataVector() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantExpr() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantFP() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantInt() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantPointerNull() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantStruct() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantTokenNone() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAConstantVector() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGlobalValue() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGlobalAlias() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGlobalIFunc() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGlobalObject() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFunction() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGlobalVariable() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUndefValue() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAPoisonValue() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAInstruction() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUnaryOperator() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isABinaryOperator() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACallInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAIntrinsicInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isADbgInfoIntrinsic() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isADbgVariableIntrinsic() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isADbgDeclareInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isADbgLabelInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAMemIntrinsic() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAMemCpyInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAMemMoveInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAMemSetInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACmpInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFCmpInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAICmpInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAExtractElementInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAGetElementPtrInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAInsertElementInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAInsertValueInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isALandingPadInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAPHINode() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isASelectInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAShuffleVectorInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAStoreInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isABranchInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAIndirectBrInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAInvokeInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAReturnInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isASwitchInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUnreachableInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAResumeInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACleanupReturnInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACatchReturnInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACatchSwitchInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACallBrInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFuncletPadInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACatchPadInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACleanupPadInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUnaryInstruction() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAAllocaInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isACastInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAAddrSpaceCastInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isABitCastInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFPExtInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFPToSIInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFPToUIInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFPTruncInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAIntToPtrInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAPtrToIntInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isASExtInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isASIToFPInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isATruncInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAUIToFPInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAZExtInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAExtractValueInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isALoadInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAVAArgInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFreezeInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAAtomicCmpXchgInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAAtomicRMWInst() const
Unexecuted instantiation: WasmEdge::LLVM::Value::isAFenceInst() const
760
  LLVM_FOR_EACH_VALUE_SUBCLASS(DECLARE_VALUE_CHECK)
761
#undef DECLARE_VALUE_CHECK
762
763
0
  std::string_view getValueName() noexcept {
764
0
    size_t Size;
765
0
    const auto Ptr = LLVMGetValueName2(Ref, &Size);
766
0
    return {Ptr, Size};
767
0
  }
768
  inline void addFnAttr(const Attribute &A) noexcept;
769
  inline void addParamAttr(unsigned Index, const Attribute &A) noexcept;
770
  inline void addCallSiteAttribute(const Attribute &A) noexcept;
771
  inline void setMetadata(Context &C, unsigned int KindID,
772
                          Metadata Node) noexcept;
773
774
31.0k
  Value getFirstParam() noexcept { return LLVMGetFirstParam(Ref); }
775
34.4k
  Value getNextParam() noexcept { return LLVMGetNextParam(Ref); }
776
3.95k
  Value getNextGlobal() noexcept { return LLVMGetNextGlobal(Ref); }
777
36.7k
  Value getNextFunction() noexcept { return LLVMGetNextFunction(Ref); }
778
0
  unsigned int countBasicBlocks() noexcept { return LLVMCountBasicBlocks(Ref); }
779
780
117k
  Type getType() const noexcept { return LLVMTypeOf(Ref); }
781
0
  Value getInitializer() noexcept { return LLVMGetInitializer(Ref); }
782
3.94k
  void setInitializer(Value ConstantVal) noexcept {
783
3.94k
    LLVMSetInitializer(Ref, ConstantVal.unwrap());
784
3.94k
  }
785
5.91k
  void setGlobalConstant(bool IsConstant) noexcept {
786
5.91k
    LLVMSetGlobalConstant(Ref, IsConstant);
787
5.91k
  }
788
20.1k
  LLVMLinkage getLinkage() noexcept { return LLVMGetLinkage(Ref); }
789
21.4k
  void setLinkage(LLVMLinkage Linkage) noexcept {
790
21.4k
    LLVMSetLinkage(Ref, Linkage);
791
21.4k
  }
792
18.3k
  void setVisibility(LLVMVisibility Viz) noexcept {
793
18.3k
    LLVMSetVisibility(Ref, Viz);
794
18.3k
  }
795
  inline void setDSOLocal(bool Local) noexcept;
796
18.3k
  void setDLLStorageClass(LLVMDLLStorageClass Class) noexcept {
797
18.3k
    LLVMSetDLLStorageClass(Ref, Class);
798
18.3k
  }
799
0
  bool getVolatile() noexcept { return LLVMGetVolatile(Ref); }
800
0
  void setVolatile(bool IsVolatile) noexcept {
801
0
    LLVMSetVolatile(Ref, IsVolatile);
802
0
  }
803
0
  bool getWeak() noexcept { return LLVMGetWeak(Ref); }
804
0
  void setWeak(bool IsWeak) noexcept { LLVMSetWeak(Ref, IsWeak); }
805
0
  unsigned int getAlignment() noexcept { return LLVMGetAlignment(Ref); }
806
21.8k
  void setAlignment(unsigned int Bytes) noexcept {
807
21.8k
    LLVMSetAlignment(Ref, Bytes);
808
21.8k
  }
809
0
  LLVMAtomicOrdering getOrdering() noexcept { return LLVMGetOrdering(Ref); }
810
0
  void setOrdering(LLVMAtomicOrdering Ordering) noexcept {
811
0
    LLVMSetOrdering(Ref, Ordering);
812
0
  }
813
0
  std::string_view getName() noexcept {
814
0
    size_t Length;
815
0
    auto Data = LLVMGetValueName2(Ref, &Length);
816
0
    return {Data, Length};
817
0
  }
818
819
  inline void addCase(Value OnVal, BasicBlock Dest) noexcept;
820
  inline void addDestination(BasicBlock Dest) noexcept;
821
  inline void addIncoming(Value IncomingValue,
822
                          BasicBlock IncomingBlocks) noexcept;
823
  inline void addIncoming(Span<const Value> IncomingValue,
824
                          Span<const BasicBlock> IncomingBlocks) noexcept;
825
  inline void eliminateUnreachableBlocks() noexcept;
826
827
private:
828
  LLVMValueRef Ref = nullptr;
829
};
830
831
struct FunctionCallee {
832
97.4k
  FunctionCallee() = default;
833
21.1k
  FunctionCallee(Type T, Value F) : Ty(T), Fn(F) {}
834
  Type Ty;
835
  Value Fn;
836
};
837
838
class Metadata {
839
public:
840
0
  constexpr Metadata(LLVMMetadataRef R) noexcept : Ref(R) {}
841
  Metadata(const Metadata &) = delete;
842
  Metadata &operator=(const Metadata &) = delete;
843
0
  Metadata(Metadata &&M) noexcept : Metadata() { swap(*this, M); }
844
0
  Metadata &operator=(Metadata &&M) noexcept {
845
0
    swap(*this, M);
846
0
    return *this;
847
0
  }
848
26.9k
  Metadata(Context &C, Span<Metadata> M) noexcept {
849
26.9k
    const auto Data = const_cast<LLVMMetadataRef *>(
850
26.9k
        reinterpret_cast<const LLVMMetadataRef *>(M.data()));
851
26.9k
    const auto Size = static_cast<unsigned int>(M.size());
852
26.9k
    Ref = LLVMMDNodeInContext2(C.unwrap(), Data, Size);
853
26.9k
  }
854
1.97k
  Metadata(Value V) noexcept : Ref(LLVMValueAsMetadata(V.unwrap())) {}
855
856
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
857
0
  constexpr auto &unwrap() const noexcept { return Ref; }
858
28.9k
  constexpr auto unwrap() noexcept { return Ref; }
859
0
  friend void swap(Metadata &LHS, Metadata &RHS) noexcept {
860
0
    using std::swap;
861
0
    swap(LHS.Ref, RHS.Ref);
862
0
  }
863
864
private:
865
  constexpr Metadata() noexcept = default;
866
  LLVMMetadataRef Ref = nullptr;
867
};
868
869
class Attribute {
870
public:
871
134k
  constexpr Attribute(LLVMAttributeRef R) noexcept : Ref(R) {}
872
  Attribute(const Attribute &) = delete;
873
  Attribute &operator=(const Attribute &) = delete;
874
0
  Attribute(Attribute &&M) noexcept : Attribute() { swap(*this, M); }
875
0
  Attribute &operator=(Attribute &&M) noexcept {
876
0
    swap(*this, M);
877
0
    return *this;
878
0
  }
879
880
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
881
218k
  constexpr auto &unwrap() const noexcept { return Ref; }
882
0
  constexpr auto unwrap() noexcept { return Ref; }
883
0
  friend void swap(Attribute &LHS, Attribute &RHS) noexcept {
884
0
    using std::swap;
885
0
    swap(LHS.Ref, RHS.Ref);
886
0
  }
887
888
  static Attribute createEnum(Context &C, unsigned int KindID,
889
13.8k
                              uint64_t Val) noexcept {
890
13.8k
    return LLVMCreateEnumAttribute(C.unwrap(), KindID, Val);
891
13.8k
  }
892
  static Attribute createString(Context &C, std::string_view Kind,
893
1.97k
                                std::string_view Val) noexcept {
894
1.97k
    return LLVMCreateStringAttribute(
895
1.97k
        C.unwrap(), Kind.data(), static_cast<unsigned int>(Kind.size()),
896
1.97k
        Val.data(), static_cast<unsigned int>(Val.size()));
897
1.97k
  }
898
899
private:
900
  constexpr Attribute() noexcept = default;
901
  LLVMAttributeRef Ref = nullptr;
902
};
903
904
Value Module::addFunction(Type Ty, LLVMLinkage Linkage,
905
16.5k
                          const char *Name) noexcept {
906
16.5k
  Value Fn = LLVMAddFunction(Ref, Name, Ty.unwrap());
907
16.5k
  Fn.setLinkage(Linkage);
908
16.5k
  return Fn;
909
16.5k
}
910
911
Value Module::addGlobal(Type Ty, bool IsConstant, LLVMLinkage Linkage,
912
4.78k
                        Value Initializer, const char *Name) noexcept {
913
4.78k
  Value G = LLVMAddGlobal(Ref, Ty.unwrap(), Name);
914
4.78k
  G.setLinkage(Linkage);
915
4.78k
  G.setGlobalConstant(IsConstant);
916
4.78k
  if (Initializer) {
917
2.80k
    G.setInitializer(Initializer);
918
2.80k
  }
919
4.78k
  return G;
920
4.78k
}
921
922
1.97k
Value Module::getNamedGlobal(const char *Name) noexcept {
923
1.97k
  return LLVMGetNamedGlobal(Ref, Name);
924
1.97k
}
925
926
Value Module::addAlias(Type Ty, Value V, const char *Name,
927
127
                       unsigned int AddrSpace [[maybe_unused]]) noexcept {
928
#if LLVM_VERSION_MAJOR >= 14
929
  return LLVMAddAlias2(Ref, Ty.unwrap(), AddrSpace, V.unwrap(), Name);
930
#else
931
127
  return LLVMAddAlias(Ref, Ty.unwrap(), V.unwrap(), Name);
932
127
#endif
933
127
}
934
935
void Module::addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
936
0
                     const Metadata &Val) noexcept {
937
0
  LLVMAddModuleFlag(Ref, Behavior, Key.data(), Key.size(), Val.unwrap());
938
0
}
939
940
void Module::addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
941
0
                     const Value &Val) noexcept {
942
0
  LLVMAddModuleFlag(Ref, Behavior, Key.data(), Key.size(),
943
0
                    Metadata(Val).unwrap());
944
0
}
945
946
void Module::addFlag(LLVMModuleFlagBehavior Behavior, std::string_view Key,
947
1.97k
                     uint32_t Val) noexcept {
948
1.97k
  Type Int32Ty = LLVMInt32TypeInContext(LLVMGetModuleContext(Ref));
949
1.97k
  LLVMAddModuleFlag(Ref, Behavior, Key.data(), Key.size(),
950
1.97k
                    Metadata(Value::getConstInt(Int32Ty, Val)).unwrap());
951
1.97k
}
952
953
1.97k
Value Module::getFirstGlobal() noexcept { return LLVMGetFirstGlobal(Ref); }
954
3.94k
Value Module::getFirstFunction() noexcept { return LLVMGetFirstFunction(Ref); }
955
956
0
Value Module::getNamedFunction(const char *Name) noexcept {
957
0
  return LLVMGetNamedFunction(Ref, Name);
958
0
}
959
960
0
Message Module::printModuleToFile(const char *Filename) noexcept {
961
0
  Message M;
962
0
  LLVMPrintModuleToFile(Ref, Filename, &M.unwrap());
963
0
  return M;
964
0
}
965
966
1.97k
Message Module::verify(LLVMVerifierFailureAction Action) noexcept {
967
1.97k
  Message M;
968
1.97k
  LLVMVerifyModule(Ref, Action, &M.unwrap());
969
1.97k
  return M;
970
1.97k
}
971
972
5.42k
Type Context::getVoidTy() noexcept { return LLVMVoidTypeInContext(Ref); }
973
5.54k
Type Context::getInt1Ty() noexcept { return LLVMInt1TypeInContext(Ref); }
974
20.9k
Type Context::getInt8Ty() noexcept { return LLVMInt8TypeInContext(Ref); }
975
4.52k
Type Context::getInt16Ty() noexcept { return LLVMInt16TypeInContext(Ref); }
976
1.21M
Type Context::getInt32Ty() noexcept { return LLVMInt32TypeInContext(Ref); }
977
4.42M
Type Context::getInt64Ty() noexcept { return LLVMInt64TypeInContext(Ref); }
978
1.97k
Type Context::getInt128Ty() noexcept { return LLVMInt128TypeInContext(Ref); }
979
1.71k
Type Context::getIntNTy(unsigned int NumBits) noexcept {
980
1.71k
  return LLVMIntTypeInContext(Ref, NumBits);
981
1.71k
}
982
1.42M
Type Context::getFloatTy() noexcept { return LLVMFloatTypeInContext(Ref); }
983
46.7k
Type Context::getDoubleTy() noexcept { return LLVMDoubleTypeInContext(Ref); }
984
985
4.98k
Value Context::getFalse() noexcept {
986
4.98k
  return Value::getConstInt(getInt1Ty(), 0);
987
4.98k
}
988
0
Value Context::getTrue() noexcept { return Value::getConstInt(getInt1Ty(), 1); }
989
18.1k
Value Context::getInt8(uint8_t C) noexcept {
990
18.1k
  return Value::getConstInt(getInt8Ty(), C);
991
18.1k
}
992
2.55k
Value Context::getInt16(uint16_t C) noexcept {
993
2.55k
  return Value::getConstInt(getInt16Ty(), C);
994
2.55k
}
995
671k
Value Context::getInt32(uint32_t C) noexcept {
996
671k
  return Value::getConstInt(getInt32Ty(), C);
997
671k
}
998
216k
Value Context::getInt64(uint64_t C) noexcept {
999
216k
  return Value::getConstInt(getInt64Ty(), C);
1000
216k
}
1001
15.6k
Value Context::getFloat(float C) noexcept {
1002
15.6k
  return Value::getConstReal(getFloatTy(), C);
1003
15.6k
}
1004
6.62k
Value Context::getDouble(double C) noexcept {
1005
6.62k
  return Value::getConstReal(getDoubleTy(), C);
1006
6.62k
}
1007
1008
55.4k
void Value::addFnAttr(const Attribute &A) noexcept {
1009
55.4k
  LLVMAddAttributeAtIndex(
1010
55.4k
      Ref, static_cast<unsigned int>(LLVMAttributeFunctionIndex), A.unwrap());
1011
55.4k
}
1012
40.3k
void Value::addParamAttr(unsigned Index, const Attribute &A) noexcept {
1013
40.3k
  LLVMAddAttributeAtIndex(Ref, 1 + Index, A.unwrap());
1014
40.3k
}
1015
123k
void Value::addCallSiteAttribute(const Attribute &A) noexcept {
1016
123k
  LLVMAddCallSiteAttribute(
1017
123k
      Ref, static_cast<unsigned int>(LLVMAttributeFunctionIndex), A.unwrap());
1018
123k
}
1019
void Value::setMetadata(Context &C, unsigned int KindID,
1020
26.9k
                        Metadata Node) noexcept {
1021
26.9k
  LLVMSetMetadata(Ref, KindID, LLVMMetadataAsValue(C.unwrap(), Node.unwrap()));
1022
26.9k
}
1023
1024
1.97k
static inline Message getDefaultTargetTriple() noexcept {
1025
1.97k
  return LLVMGetDefaultTargetTriple();
1026
1.97k
}
compiler.cpp:WasmEdge::LLVM::getDefaultTargetTriple()
Line
Count
Source
1024
1.97k
static inline Message getDefaultTargetTriple() noexcept {
1025
1.97k
  return LLVMGetDefaultTargetTriple();
1026
1.97k
}
Unexecuted instantiation: codegen.cpp:WasmEdge::LLVM::getDefaultTargetTriple()
Unexecuted instantiation: data.cpp:WasmEdge::LLVM::getDefaultTargetTriple()
Unexecuted instantiation: jit.cpp:WasmEdge::LLVM::getDefaultTargetTriple()
1027
1.97k
static inline Message getHostCPUName() noexcept { return LLVMGetHostCPUName(); }
compiler.cpp:WasmEdge::LLVM::getHostCPUName()
Line
Count
Source
1027
1.97k
static inline Message getHostCPUName() noexcept { return LLVMGetHostCPUName(); }
Unexecuted instantiation: codegen.cpp:WasmEdge::LLVM::getHostCPUName()
Unexecuted instantiation: data.cpp:WasmEdge::LLVM::getHostCPUName()
Unexecuted instantiation: jit.cpp:WasmEdge::LLVM::getHostCPUName()
1028
3.94k
static inline Message getHostCPUFeatures() noexcept {
1029
3.94k
  return LLVMGetHostCPUFeatures();
1030
3.94k
}
compiler.cpp:WasmEdge::LLVM::getHostCPUFeatures()
Line
Count
Source
1028
3.94k
static inline Message getHostCPUFeatures() noexcept {
1029
3.94k
  return LLVMGetHostCPUFeatures();
1030
3.94k
}
Unexecuted instantiation: codegen.cpp:WasmEdge::LLVM::getHostCPUFeatures()
Unexecuted instantiation: data.cpp:WasmEdge::LLVM::getHostCPUFeatures()
Unexecuted instantiation: jit.cpp:WasmEdge::LLVM::getHostCPUFeatures()
1031
1032
class BasicBlock {
1033
public:
1034
128k
  constexpr BasicBlock() noexcept = default;
1035
110k
  constexpr BasicBlock(LLVMBasicBlockRef R) noexcept : Ref(R) {}
1036
  BasicBlock(const BasicBlock &) = default;
1037
  BasicBlock &operator=(const BasicBlock &) = default;
1038
91.2k
  BasicBlock(BasicBlock &&B) noexcept : BasicBlock() { swap(*this, B); }
1039
2.90k
  BasicBlock &operator=(BasicBlock &&B) noexcept {
1040
2.90k
    swap(*this, B);
1041
2.90k
    return *this;
1042
2.90k
  }
1043
1044
76.1k
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1045
0
  constexpr auto &unwrap() const noexcept { return Ref; }
1046
245k
  constexpr auto &unwrap() noexcept { return Ref; }
1047
94.1k
  friend void swap(BasicBlock &LHS, BasicBlock &RHS) noexcept {
1048
94.1k
    using std::swap;
1049
94.1k
    swap(LHS.Ref, RHS.Ref);
1050
94.1k
  }
1051
1052
90.8k
  static BasicBlock create(Context &C, Value F, const char *Name) noexcept {
1053
90.8k
    return LLVMAppendBasicBlockInContext(C.unwrap(), F.unwrap(), Name);
1054
90.8k
  }
1055
0
  void erase() noexcept { LLVMDeleteBasicBlock(Ref); }
1056
1057
private:
1058
  LLVMBasicBlockRef Ref = nullptr;
1059
};
1060
1061
35.4k
void Value::addCase(Value OnVal, BasicBlock Dest) noexcept {
1062
35.4k
  LLVMAddCase(Ref, OnVal.unwrap(), Dest.unwrap());
1063
35.4k
}
1064
1065
0
void Value::addDestination(BasicBlock Dest) noexcept {
1066
0
  LLVMAddDestination(Ref, Dest.unwrap());
1067
0
}
1068
1069
void Value::addIncoming(Value IncomingValue,
1070
16.9k
                        BasicBlock IncomingBlocks) noexcept {
1071
16.9k
  LLVMAddIncoming(Ref, &IncomingValue.unwrap(), &IncomingBlocks.unwrap(), 1);
1072
16.9k
}
1073
1074
void Value::addIncoming(Span<const Value> IncomingValue,
1075
0
                        Span<const BasicBlock> IncomingBlocks) noexcept {
1076
0
  assuming(IncomingBlocks.size() == IncomingValue.size());
1077
0
  const auto ValueData = const_cast<LLVMValueRef *>(
1078
0
      reinterpret_cast<const LLVMValueRef *>(IncomingValue.data()));
1079
0
  const auto BlockData = const_cast<LLVMBasicBlockRef *>(
1080
0
      reinterpret_cast<const LLVMBasicBlockRef *>(IncomingBlocks.data()));
1081
0
  const auto Size = static_cast<unsigned int>(IncomingValue.size());
1082
0
  LLVMAddIncoming(Ref, ValueData, BlockData, Size);
1083
0
}
1084
1085
class Builder {
1086
private:
1087
393k
  LLVMValueRef getFn() noexcept {
1088
393k
    return LLVMGetBasicBlockParent(LLVMGetInsertBlock(Ref));
1089
393k
  }
1090
393k
  LLVMModuleRef getMod() noexcept { return LLVMGetGlobalParent(getFn()); }
1091
298k
  LLVMContextRef getCtx() noexcept { return LLVMGetModuleContext(getMod()); }
1092
1093
public:
1094
  constexpr Builder() noexcept = default;
1095
0
  constexpr Builder(LLVMBuilderRef R) noexcept : Ref(R) {}
1096
  Builder(const Builder &) = delete;
1097
  Builder &operator=(const Builder &) = delete;
1098
0
  Builder(Builder &&B) noexcept : Builder() { swap(*this, B); }
1099
0
  Builder &operator=(Builder &&B) noexcept {
1100
0
    swap(*this, B);
1101
0
    return *this;
1102
0
  }
1103
16.5k
  ~Builder() noexcept { LLVMDisposeBuilder(Ref); }
1104
1105
16.5k
  Builder(Context &C) noexcept : Ref(LLVMCreateBuilderInContext(C.unwrap())) {}
1106
1107
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1108
0
  constexpr auto &unwrap() const noexcept { return Ref; }
1109
0
  constexpr auto &unwrap() noexcept { return Ref; }
1110
0
  friend void swap(Builder &LHS, Builder &RHS) noexcept {
1111
0
    using std::swap;
1112
0
    swap(LHS.Ref, RHS.Ref);
1113
0
  }
1114
1115
93.2k
  void positionAtEnd(BasicBlock B) noexcept {
1116
93.2k
    LLVMPositionBuilderAtEnd(Ref, B.unwrap());
1117
93.2k
  }
1118
19.8k
  BasicBlock getInsertBlock() noexcept { return LLVMGetInsertBlock(Ref); }
1119
1120
5.84k
  Value createRetVoid() noexcept { return LLVMBuildRetVoid(Ref); }
1121
9.05k
  Value createRet(Value V) noexcept { return LLVMBuildRet(Ref, V.unwrap()); }
1122
316
  Value createAggregateRet(Span<const Value> RetVals) noexcept {
1123
316
    const auto Data = const_cast<LLVMValueRef *>(
1124
316
        reinterpret_cast<const LLVMValueRef *>(RetVals.data()));
1125
316
    const auto Size = static_cast<unsigned int>(RetVals.size());
1126
316
    return LLVMBuildAggregateRet(Ref, Data, Size);
1127
316
  }
1128
26.9k
  Value createBr(BasicBlock Dest) noexcept {
1129
26.9k
    return LLVMBuildBr(Ref, Dest.unwrap());
1130
26.9k
  }
1131
35.8k
  Value createCondBr(Value If, BasicBlock Then, BasicBlock Else) noexcept {
1132
35.8k
    return LLVMBuildCondBr(Ref, If.unwrap(), Then.unwrap(), Else.unwrap());
1133
35.8k
  }
1134
925
  Value createSwitch(Value V, BasicBlock Else, unsigned int NumCases) noexcept {
1135
925
    return LLVMBuildSwitch(Ref, V.unwrap(), Else.unwrap(), NumCases);
1136
925
  }
1137
0
  Value createIndirectBr(Value Addr, unsigned int NumDests) noexcept {
1138
0
    return LLVMBuildIndirectBr(Ref, Addr.unwrap(), NumDests);
1139
0
  }
1140
11.9k
  Value createUnreachable() noexcept { return LLVMBuildUnreachable(Ref); }
1141
1142
15.4k
  Value createAdd(Value LHS, Value RHS, const char *Name = "") noexcept {
1143
15.4k
    return LLVMBuildAdd(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1144
15.4k
  }
1145
0
  Value createNSWAdd(Value LHS, Value RHS, const char *Name = "") noexcept {
1146
0
    return LLVMBuildNSWAdd(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1147
0
  }
1148
0
  Value createNUWAdd(Value LHS, Value RHS, const char *Name = "") noexcept {
1149
0
    return LLVMBuildNUWAdd(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1150
0
  }
1151
2.42k
  Value createFAdd(Value LHS, Value RHS, const char *Name = "") noexcept {
1152
2.42k
    Value Ret = createIntrinsic(
1153
2.42k
        Core::ExperimentalConstrainedFAdd, {LHS.getType()},
1154
2.42k
        {LHS, RHS, getConstrainedFPRounding(), getConstrainedFPExcept()}, Name);
1155
2.42k
    Ret.addCallSiteAttribute(
1156
2.42k
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1157
2.42k
    return Ret;
1158
2.42k
  }
1159
2.68k
  Value createSub(Value LHS, Value RHS, const char *Name = "") noexcept {
1160
2.68k
    return LLVMBuildSub(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1161
2.68k
  }
1162
0
  Value createNSWSub(Value LHS, Value RHS, const char *Name = "") noexcept {
1163
0
    return LLVMBuildNSWSub(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1164
0
  }
1165
0
  Value createNUWSub(Value LHS, Value RHS, const char *Name = "") noexcept {
1166
0
    return LLVMBuildNUWSub(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1167
0
  }
1168
881
  Value createFSub(Value LHS, Value RHS, const char *Name = "") noexcept {
1169
881
    Value Ret = createIntrinsic(
1170
881
        Core::ExperimentalConstrainedFSub, {LHS.getType()},
1171
881
        {LHS, RHS, getConstrainedFPRounding(), getConstrainedFPExcept()}, Name);
1172
881
    Ret.addCallSiteAttribute(
1173
881
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1174
881
    return Ret;
1175
881
  }
1176
3.37k
  Value createMul(Value LHS, Value RHS, const char *Name = "") noexcept {
1177
3.37k
    return LLVMBuildMul(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1178
3.37k
  }
1179
0
  Value createNSWMul(Value LHS, Value RHS, const char *Name = "") noexcept {
1180
0
    return LLVMBuildNSWMul(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1181
0
  }
1182
0
  Value createNUWMul(Value LHS, Value RHS, const char *Name = "") noexcept {
1183
0
    return LLVMBuildNUWMul(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1184
0
  }
1185
857
  Value createFMul(Value LHS, Value RHS, const char *Name = "") noexcept {
1186
857
    Value Ret = createIntrinsic(
1187
857
        Core::ExperimentalConstrainedFMul, {LHS.getType()},
1188
857
        {LHS, RHS, getConstrainedFPRounding(), getConstrainedFPExcept()}, Name);
1189
857
    Ret.addCallSiteAttribute(
1190
857
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1191
857
    return Ret;
1192
857
  }
1193
3.59k
  Value createUDiv(Value LHS, Value RHS, const char *Name = "") noexcept {
1194
3.59k
    return LLVMBuildUDiv(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1195
3.59k
  }
1196
0
  Value createExactUDiv(Value LHS, Value RHS, const char *Name = "") noexcept {
1197
0
    return LLVMBuildExactUDiv(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1198
0
  }
1199
1.83k
  Value createSDiv(Value LHS, Value RHS, const char *Name = "") noexcept {
1200
1.83k
    return LLVMBuildSDiv(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1201
1.83k
  }
1202
0
  Value createExactSDiv(Value LHS, Value RHS, const char *Name = "") noexcept {
1203
0
    return LLVMBuildExactSDiv(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1204
0
  }
1205
804
  Value createFDiv(Value LHS, Value RHS, const char *Name = "") noexcept {
1206
804
    Value Ret = createIntrinsic(
1207
804
        Core::ExperimentalConstrainedFDiv, {LHS.getType()},
1208
804
        {LHS, RHS, getConstrainedFPRounding(), getConstrainedFPExcept()}, Name);
1209
804
    Ret.addCallSiteAttribute(
1210
804
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1211
804
    return Ret;
1212
804
  }
1213
1.55k
  Value createURem(Value LHS, Value RHS, const char *Name = "") noexcept {
1214
1.55k
    return LLVMBuildURem(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1215
1.55k
  }
1216
1.38k
  Value createSRem(Value LHS, Value RHS, const char *Name = "") noexcept {
1217
1.38k
    return LLVMBuildSRem(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1218
1.38k
  }
1219
3.07k
  Value createShl(Value LHS, Value RHS, const char *Name = "") noexcept {
1220
3.07k
    return LLVMBuildShl(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1221
3.07k
  }
1222
4.43k
  Value createLShr(Value LHS, Value RHS, const char *Name = "") noexcept {
1223
4.43k
    return LLVMBuildLShr(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1224
4.43k
  }
1225
4.00k
  Value createAShr(Value LHS, Value RHS, const char *Name = "") noexcept {
1226
4.00k
    return LLVMBuildAShr(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1227
4.00k
  }
1228
15.0k
  Value createAnd(Value LHS, Value RHS, const char *Name = "") noexcept {
1229
15.0k
    return LLVMBuildAnd(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1230
15.0k
  }
1231
7.10k
  Value createOr(Value LHS, Value RHS, const char *Name = "") noexcept {
1232
7.10k
    return LLVMBuildOr(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1233
7.10k
  }
1234
2.48k
  Value createXor(Value LHS, Value RHS, const char *Name = "") noexcept {
1235
2.48k
    return LLVMBuildXor(Ref, LHS.unwrap(), RHS.unwrap(), Name);
1236
2.48k
  }
1237
4.24k
  Value createNeg(Value V, const char *Name = "") noexcept {
1238
4.24k
    return LLVMBuildNeg(Ref, V.unwrap(), Name);
1239
4.24k
  }
1240
2.78k
  Value createFNeg(Value V, const char *Name = "") noexcept {
1241
2.78k
    return LLVMBuildFNeg(Ref, V.unwrap(), Name);
1242
2.78k
  }
1243
919
  Value createNot(Value V, const char *Name = "") noexcept {
1244
919
    return LLVMBuildNot(Ref, V.unwrap(), Name);
1245
919
  }
1246
3.08M
  Value createAlloca(Type Ty, const char *Name = "") noexcept {
1247
3.08M
    return LLVMBuildAlloca(Ref, Ty.unwrap(), Name);
1248
3.08M
  }
1249
1.15k
  Value createArrayAlloca(Type Ty, Value Val, const char *Name = "") noexcept {
1250
1.15k
    return LLVMBuildArrayAlloca(Ref, Ty.unwrap(), Val.unwrap(), Name);
1251
1.15k
  }
1252
  Value createLoad(Type Ty, Value PointerVal, bool Volatile = false,
1253
97.3k
                   const char *Name = "") noexcept {
1254
97.3k
    auto Ret = LLVMBuildLoad2(Ref, Ty.unwrap(), PointerVal.unwrap(), Name);
1255
97.3k
    if (Volatile) {
1256
17.4k
      LLVMSetVolatile(Ret, true);
1257
17.4k
    }
1258
97.3k
    return Ret;
1259
97.3k
  }
1260
3.09M
  Value createStore(Value Val, Value Ptr, bool Volatile = false) noexcept {
1261
3.09M
    auto Ret = LLVMBuildStore(Ref, Val.unwrap(), Ptr.unwrap());
1262
3.09M
    if (Volatile) {
1263
4.64k
      LLVMSetVolatile(Ret, true);
1264
4.64k
    }
1265
3.09M
    return Ret;
1266
3.09M
  }
1267
1268
  Value createInBoundsGEP1(Type Ty, Value Pointer, Value Idx0,
1269
62.3k
                           const char *Name = "") noexcept {
1270
62.3k
    LLVMValueRef Data[1] = {Idx0.unwrap()};
1271
62.3k
    return LLVMBuildInBoundsGEP2(Ref, Ty.unwrap(), Pointer.unwrap(), Data,
1272
62.3k
                                 static_cast<unsigned>(std::size(Data)), Name);
1273
62.3k
  }
1274
  Value createInBoundsGEP2(Type Ty, Value Pointer, Value Idx0, Value Idx1,
1275
5.97k
                           const char *Name = "") noexcept {
1276
5.97k
    LLVMValueRef Data[2] = {Idx0.unwrap(), Idx1.unwrap()};
1277
5.97k
    return LLVMBuildInBoundsGEP2(Ref, Ty.unwrap(), Pointer.unwrap(), Data,
1278
5.97k
                                 static_cast<unsigned>(std::size(Data)), Name);
1279
5.97k
  }
1280
  Value createConstInBoundsGEP1_64(Type Ty, Value Pointer, uint64_t Idx0,
1281
8.53k
                                   const char *Name = "") noexcept {
1282
8.53k
    Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
1283
8.53k
    LLVMValueRef Data[1] = {Value::getConstInt(Int64Ty, Idx0).unwrap()};
1284
8.53k
    return LLVMBuildInBoundsGEP2(Ref, Ty.unwrap(), Pointer.unwrap(), Data,
1285
8.53k
                                 static_cast<unsigned>(std::size(Data)), Name);
1286
8.53k
  }
1287
1288
  Value createConstInBoundsGEP2_64(Type Ty, Value Pointer, uint64_t Idx0,
1289
                                   uint64_t Idx1,
1290
0
                                   const char *Name = "") noexcept {
1291
0
    Type Int64Ty = LLVMInt64TypeInContext(LLVMGetTypeContext(Ty.unwrap()));
1292
0
    LLVMValueRef Data[2] = {Value::getConstInt(Int64Ty, Idx0).unwrap(),
1293
0
                            Value::getConstInt(Int64Ty, Idx1).unwrap()};
1294
0
    return LLVMBuildInBoundsGEP2(Ref, Ty.unwrap(), Pointer.unwrap(), Data,
1295
0
                                 static_cast<unsigned>(std::size(Data)), Name);
1296
0
  }
1297
1298
55.7k
  Value createTrunc(Value Val, Type DestTy, const char *Name = "") noexcept {
1299
55.7k
    return LLVMBuildTrunc(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1300
55.7k
  }
1301
71.9k
  Value createZExt(Value Val, Type DestTy, const char *Name = "") noexcept {
1302
71.9k
    return LLVMBuildZExt(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1303
71.9k
  }
1304
25.2k
  Value createSExt(Value Val, Type DestTy, const char *Name = "") noexcept {
1305
25.2k
    return LLVMBuildSExt(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1306
25.2k
  }
1307
10.1k
  Value createFPToUI(Value Val, Type DestTy, const char *Name = "") noexcept {
1308
10.1k
    return LLVMBuildFPToUI(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1309
10.1k
  }
1310
3.98k
  Value createFPToSI(Value Val, Type DestTy, const char *Name = "") noexcept {
1311
3.98k
    return LLVMBuildFPToSI(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1312
3.98k
  }
1313
16.8k
  Value createUIToFP(Value Val, Type DestTy, const char *Name = "") noexcept {
1314
16.8k
    return LLVMBuildUIToFP(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1315
16.8k
  }
1316
10.1k
  Value createSIToFP(Value Val, Type DestTy, const char *Name = "") noexcept {
1317
10.1k
    return LLVMBuildSIToFP(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1318
10.1k
  }
1319
703
  Value createFPTrunc(Value Val, Type DestTy, const char *Name = "") noexcept {
1320
703
    Value Ret = createIntrinsic(
1321
703
        Core::ExperimentalConstrainedFPTrunc, {DestTy, Val.getType()},
1322
703
        {Val, getConstrainedFPRounding(), getConstrainedFPExcept()}, Name);
1323
703
    Ret.addCallSiteAttribute(
1324
703
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1325
703
    return Ret;
1326
703
  }
1327
629
  Value createFPExt(Value Val, Type DestTy, const char *Name = "") noexcept {
1328
629
    Value Ret = createIntrinsic(Core::ExperimentalConstrainedFPExt,
1329
629
                                {DestTy, Val.getType()},
1330
629
                                {Val, getConstrainedFPExcept()}, Name);
1331
629
    Ret.addCallSiteAttribute(
1332
629
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1333
629
    return Ret;
1334
629
  }
1335
0
  Value createPtrToInt(Value Val, Type DestTy, const char *Name = "") noexcept {
1336
0
    return LLVMBuildPtrToInt(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1337
0
  }
1338
0
  Value createIntToPtr(Value Val, Type DestTy, const char *Name = "") noexcept {
1339
0
    return LLVMBuildIntToPtr(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1340
0
  }
1341
253k
  Value createBitCast(Value Val, Type DestTy, const char *Name = "") noexcept {
1342
253k
    return LLVMBuildBitCast(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1343
253k
  }
1344
  Value createZExtOrBitCast(Value Val, Type DestTy,
1345
0
                            const char *Name = "") noexcept {
1346
0
    return LLVMBuildZExtOrBitCast(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1347
0
  }
1348
  Value createSExtOrBitCast(Value Val, Type DestTy,
1349
0
                            const char *Name = "") noexcept {
1350
0
    return LLVMBuildSExtOrBitCast(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1351
0
  }
1352
  Value createTruncOrBitCast(Value Val, Type DestTy,
1353
0
                             const char *Name = "") noexcept {
1354
0
    return LLVMBuildTruncOrBitCast(Ref, Val.unwrap(), DestTy.unwrap(), Name);
1355
0
  }
1356
  Value createZExtOrTrunc(Value Val, Type DestTy,
1357
1.73k
                          const char *Name = "") noexcept {
1358
1.73k
    const auto VTy = Val.getType();
1359
1.73k
    assuming(DestTy.isIntegerTy() || DestTy.isVectorTy());
1360
1.73k
    assuming(VTy.isIntegerTy() || VTy.isVectorTy());
1361
1.73k
    const auto VTySize = VTy.getPrimitiveSizeInBits();
1362
1.73k
    const auto DestTySize = DestTy.getPrimitiveSizeInBits();
1363
1.73k
    if (VTySize < DestTySize) {
1364
500
      return createZExt(Val, DestTy, Name);
1365
500
    }
1366
1.23k
    if (VTySize > DestTySize) {
1367
0
      return createTrunc(Val, DestTy, Name);
1368
0
    }
1369
1.23k
    return Val;
1370
1.23k
  }
1371
  Value createSExtOrTrunc(Value Val, Type DestTy,
1372
0
                          const char *Name = "") noexcept {
1373
0
    const auto VTy = Val.getType();
1374
0
    assuming(DestTy.isIntegerTy() || DestTy.isVectorTy());
1375
0
    assuming(VTy.isIntegerTy() || VTy.isVectorTy());
1376
0
    const auto VTySize = VTy.getPrimitiveSizeInBits();
1377
0
    const auto DestTySize = DestTy.getPrimitiveSizeInBits();
1378
0
    if (VTySize < DestTySize) {
1379
0
      return createSExt(Val, DestTy, Name);
1380
0
    }
1381
0
    if (VTySize > DestTySize) {
1382
0
      return createTrunc(Val, DestTy, Name);
1383
0
    }
1384
0
    return Val;
1385
0
  }
1386
1387
  Value createICmp(LLVMIntPredicate Op, Value LHS, Value RHS,
1388
70.3k
                   const char *Name = "") noexcept {
1389
70.3k
    return LLVMBuildICmp(Ref, Op, LHS.unwrap(), RHS.unwrap(), Name);
1390
70.3k
  }
1391
11.6k
  Value createICmpEQ(Value LHS, Value RHS, const char *Name = "") noexcept {
1392
11.6k
    return createICmp(LLVMIntEQ, LHS, RHS, Name);
1393
11.6k
  }
1394
19.0k
  Value createICmpNE(Value LHS, Value RHS, const char *Name = "") noexcept {
1395
19.0k
    return createICmp(LLVMIntNE, LHS, RHS, Name);
1396
19.0k
  }
1397
6.06k
  Value createICmpUGT(Value LHS, Value RHS, const char *Name = "") noexcept {
1398
6.06k
    return createICmp(LLVMIntUGT, LHS, RHS, Name);
1399
6.06k
  }
1400
4.05k
  Value createICmpUGE(Value LHS, Value RHS, const char *Name = "") noexcept {
1401
4.05k
    return createICmp(LLVMIntUGE, LHS, RHS, Name);
1402
4.05k
  }
1403
6.12k
  Value createICmpULT(Value LHS, Value RHS, const char *Name = "") noexcept {
1404
6.12k
    return createICmp(LLVMIntULT, LHS, RHS, Name);
1405
6.12k
  }
1406
2.26k
  Value createICmpULE(Value LHS, Value RHS, const char *Name = "") noexcept {
1407
2.26k
    return createICmp(LLVMIntULE, LHS, RHS, Name);
1408
2.26k
  }
1409
2.63k
  Value createICmpSGT(Value LHS, Value RHS, const char *Name = "") noexcept {
1410
2.63k
    return createICmp(LLVMIntSGT, LHS, RHS, Name);
1411
2.63k
  }
1412
1.53k
  Value createICmpSGE(Value LHS, Value RHS, const char *Name = "") noexcept {
1413
1.53k
    return createICmp(LLVMIntSGE, LHS, RHS, Name);
1414
1.53k
  }
1415
8.98k
  Value createICmpSLT(Value LHS, Value RHS, const char *Name = "") noexcept {
1416
8.98k
    return createICmp(LLVMIntSLT, LHS, RHS, Name);
1417
8.98k
  }
1418
2.87k
  Value createICmpSLE(Value LHS, Value RHS, const char *Name = "") noexcept {
1419
2.87k
    return createICmp(LLVMIntSLE, LHS, RHS, Name);
1420
2.87k
  }
1421
  Value createFCmp(LLVMRealPredicate Op, Value LHS, Value RHS,
1422
10.6k
                   const char *Name = "") noexcept {
1423
10.6k
    return LLVMBuildFCmp(Ref, Op, LHS.unwrap(), RHS.unwrap(), Name);
1424
10.6k
  }
1425
238
  Value createFCmpOEQ(Value LHS, Value RHS, const char *Name = "") noexcept {
1426
238
    return LLVMBuildFCmp(Ref, LLVMRealOEQ, LHS.unwrap(), RHS.unwrap(), Name);
1427
238
  }
1428
985
  Value createFCmpOGT(Value LHS, Value RHS, const char *Name = "") noexcept {
1429
985
    return LLVMBuildFCmp(Ref, LLVMRealOGT, LHS.unwrap(), RHS.unwrap(), Name);
1430
985
  }
1431
13.4k
  Value createFCmpOGE(Value LHS, Value RHS, const char *Name = "") noexcept {
1432
13.4k
    return LLVMBuildFCmp(Ref, LLVMRealOGE, LHS.unwrap(), RHS.unwrap(), Name);
1433
13.4k
  }
1434
1.10k
  Value createFCmpOLT(Value LHS, Value RHS, const char *Name = "") noexcept {
1435
1.10k
    return LLVMBuildFCmp(Ref, LLVMRealOLT, LHS.unwrap(), RHS.unwrap(), Name);
1436
1.10k
  }
1437
198
  Value createFCmpOLE(Value LHS, Value RHS, const char *Name = "") noexcept {
1438
198
    return LLVMBuildFCmp(Ref, LLVMRealOLE, LHS.unwrap(), RHS.unwrap(), Name);
1439
198
  }
1440
0
  Value createFCmpONE(Value LHS, Value RHS, const char *Name = "") noexcept {
1441
0
    return LLVMBuildFCmp(Ref, LLVMRealONE, LHS.unwrap(), RHS.unwrap(), Name);
1442
0
  }
1443
7.25k
  Value createFCmpORD(Value LHS, Value RHS, const char *Name = "") noexcept {
1444
7.25k
    return LLVMBuildFCmp(Ref, LLVMRealORD, LHS.unwrap(), RHS.unwrap(), Name);
1445
7.25k
  }
1446
2.71k
  Value createFCmpUNO(Value LHS, Value RHS, const char *Name = "") noexcept {
1447
2.71k
    return LLVMBuildFCmp(Ref, LLVMRealUNO, LHS.unwrap(), RHS.unwrap(), Name);
1448
2.71k
  }
1449
1.75k
  Value createFCmpUEQ(Value LHS, Value RHS, const char *Name = "") noexcept {
1450
1.75k
    return LLVMBuildFCmp(Ref, LLVMRealUEQ, LHS.unwrap(), RHS.unwrap(), Name);
1451
1.75k
  }
1452
0
  Value createFCmpUGT(Value LHS, Value RHS, const char *Name = "") noexcept {
1453
0
    return LLVMBuildFCmp(Ref, LLVMRealUGT, LHS.unwrap(), RHS.unwrap(), Name);
1454
0
  }
1455
961
  Value createFCmpUGE(Value LHS, Value RHS, const char *Name = "") noexcept {
1456
961
    return LLVMBuildFCmp(Ref, LLVMRealUGE, LHS.unwrap(), RHS.unwrap(), Name);
1457
961
  }
1458
6.87k
  Value createFCmpULT(Value LHS, Value RHS, const char *Name = "") noexcept {
1459
6.87k
    return LLVMBuildFCmp(Ref, LLVMRealULT, LHS.unwrap(), RHS.unwrap(), Name);
1460
6.87k
  }
1461
0
  Value createFCmpULE(Value LHS, Value RHS, const char *Name = "") noexcept {
1462
0
    return LLVMBuildFCmp(Ref, LLVMRealULE, LHS.unwrap(), RHS.unwrap(), Name);
1463
0
  }
1464
117
  Value createFCmpUNE(Value LHS, Value RHS, const char *Name = "") noexcept {
1465
117
    return LLVMBuildFCmp(Ref, LLVMRealUNE, LHS.unwrap(), RHS.unwrap(), Name);
1466
117
  }
1467
6.04k
  Value createPHI(Type Ty, const char *Name = "") noexcept {
1468
6.04k
    return LLVMBuildPhi(Ref, Ty.unwrap(), Name);
1469
6.04k
  }
1470
  Value createCall(FunctionCallee Callee, Span<const Value> Args,
1471
112k
                   const char *Name = "") noexcept {
1472
112k
    const auto Data = const_cast<LLVMValueRef *>(
1473
112k
        reinterpret_cast<const LLVMValueRef *>(Args.data()));
1474
112k
    const auto Size = static_cast<unsigned int>(Args.size());
1475
112k
    Value Ret = LLVMBuildCall2(Ref, Callee.Ty.unwrap(), Callee.Fn.unwrap(),
1476
112k
                               Data, Size, Name);
1477
112k
    Ret.addCallSiteAttribute(
1478
112k
        LLVMCreateEnumAttribute(getCtx(), LLVM::Core::StrictFP, 0));
1479
112k
    return Ret;
1480
112k
  }
1481
  Value createSelect(Value If, Value Then, Value Else,
1482
28.1k
                     const char *Name = "") noexcept {
1483
28.1k
    return LLVMBuildSelect(Ref, If.unwrap(), Then.unwrap(), Else.unwrap(),
1484
28.1k
                           Name);
1485
28.1k
  }
1486
  Value createExtractElement(Value VecVal, Value Index,
1487
2.23k
                             const char *Name = "") noexcept {
1488
2.23k
    return LLVMBuildExtractElement(Ref, VecVal.unwrap(), Index.unwrap(), Name);
1489
2.23k
  }
1490
  Value createInsertElement(Value VecVal, Value EltVal, Value Index,
1491
80.2k
                            const char *Name = "") noexcept {
1492
80.2k
    return LLVMBuildInsertElement(Ref, VecVal.unwrap(), EltVal.unwrap(),
1493
80.2k
                                  Index.unwrap(), Name);
1494
80.2k
  }
1495
  Value createShuffleVector(Value V1, Value V2, Value Mask,
1496
94.5k
                            const char *Name = "") noexcept {
1497
94.5k
    return LLVMBuildShuffleVector(Ref, V1.unwrap(), V2.unwrap(), Mask.unwrap(),
1498
94.5k
                                  Name);
1499
94.5k
  }
1500
  Value createExtractValue(Value AggVal, unsigned int Index,
1501
21.9k
                           const char *Name = "") noexcept {
1502
21.9k
    return LLVMBuildExtractValue(Ref, AggVal.unwrap(), Index, Name);
1503
21.9k
  }
1504
  Value createInsertValue(Value AggVal, Value EltVal, unsigned int Index,
1505
0
                          const char *Name = "") noexcept {
1506
0
    return LLVMBuildInsertValue(Ref, AggVal.unwrap(), EltVal.unwrap(), Index,
1507
0
                                Name);
1508
0
  }
1509
1510
666
  Value createIsNull(Value Val, const char *Name = "") noexcept {
1511
666
    return LLVMBuildIsNull(Ref, Val.unwrap(), Name);
1512
666
  }
1513
0
  Value createIsNotNull(Value Val, const char *Name = "") noexcept {
1514
0
    return LLVMBuildIsNotNull(Ref, Val.unwrap(), Name);
1515
0
  }
1516
  Value createFence(LLVMAtomicOrdering Ordering, bool SingleThread = false,
1517
230
                    const char *Name = "") noexcept {
1518
230
    return LLVMBuildFence(Ref, Ordering, SingleThread, Name);
1519
230
  }
1520
  Value createAtomicRMW(LLVMAtomicRMWBinOp Op, Value Ptr, Value Val,
1521
                        LLVMAtomicOrdering Ordering,
1522
0
                        bool SingleThread = false) noexcept {
1523
0
    return LLVMBuildAtomicRMW(Ref, Op, Ptr.unwrap(), Val.unwrap(), Ordering,
1524
0
                              SingleThread);
1525
0
  }
1526
  Value createAtomicCmpXchg(Value Ptr, Value Cmp, Value New,
1527
                            LLVMAtomicOrdering SuccessOrdering,
1528
                            LLVMAtomicOrdering FailureOrdering,
1529
0
                            bool SingleThread = false) noexcept {
1530
0
    return LLVMBuildAtomicCmpXchg(Ref, Ptr.unwrap(), Cmp.unwrap(), New.unwrap(),
1531
0
                                  SuccessOrdering, FailureOrdering,
1532
0
                                  SingleThread);
1533
0
  }
1534
1535
  Value createIntrinsic(unsigned int ID, Span<const Type> Types,
1536
                        Span<const Value> Args,
1537
56.2k
                        const char *Name = "") noexcept {
1538
56.2k
    FunctionCallee C;
1539
56.2k
    {
1540
56.2k
      const auto Data = const_cast<LLVMTypeRef *>(
1541
56.2k
          reinterpret_cast<const LLVMTypeRef *>(Types.data()));
1542
56.2k
      const auto Size = static_cast<unsigned int>(Types.size());
1543
56.2k
      C.Fn = LLVMGetIntrinsicDeclaration(getMod(), ID, Data, Size);
1544
56.2k
      C.Ty = LLVMIntrinsicGetType(getCtx(), ID, Data, Size);
1545
56.2k
    }
1546
56.2k
    return createCall(C, Args, Name);
1547
56.2k
  }
1548
  Value createUnaryIntrinsic(unsigned int ID, Value V,
1549
39.2k
                             const char *Name = "") noexcept {
1550
39.2k
    FunctionCallee C;
1551
39.2k
    {
1552
39.2k
      LLVMTypeRef ParamTypes[1] = {V.getType().unwrap()};
1553
39.2k
      C.Fn = LLVMGetIntrinsicDeclaration(getMod(), ID, ParamTypes, 1);
1554
39.2k
      C.Ty = LLVMIntrinsicGetType(getCtx(), ID, ParamTypes, 1);
1555
39.2k
    }
1556
39.2k
    return createCall(C, {V}, Name);
1557
39.2k
  }
1558
  Value createBinaryIntrinsic(unsigned int ID, Value LHS, Value RHS,
1559
0
                              const char *Name = "") noexcept {
1560
0
    FunctionCallee C;
1561
0
    {
1562
0
      LLVMTypeRef ParamTypes[2] = {LHS.getType().unwrap(),
1563
0
                                   RHS.getType().unwrap()};
1564
0
      C.Fn = LLVMGetIntrinsicDeclaration(getMod(), ID, ParamTypes, 2);
1565
0
      C.Ty = LLVMIntrinsicGetType(getCtx(), ID, ParamTypes, 2);
1566
0
    }
1567
0
    return createCall(C, {LHS, RHS}, Name);
1568
0
  }
1569
1570
  Value createVectorSplat(unsigned int ElementCount, Value V,
1571
35.4k
                          const char *Name = "") noexcept {
1572
35.4k
    Value Zero = Value::getConstInt(LLVMInt32TypeInContext(getCtx()), 0);
1573
35.4k
    auto Empty =
1574
35.4k
        Value::getUndef(Type::getVectorType(V.getType(), ElementCount));
1575
35.4k
    auto One = createInsertElement(Empty, V, Zero);
1576
35.4k
    std::vector<Value> Mask(ElementCount, Zero);
1577
35.4k
    return createShuffleVector(One, Empty, Value::getConstVector(Mask), Name);
1578
35.4k
  }
1579
1580
33.0k
  Value createLikely(Value V) noexcept {
1581
33.0k
    Type Int1Ty = LLVMInt1TypeInContext(getCtx());
1582
33.0k
    return createIntrinsic(LLVM::Core::Expect, {Int1Ty},
1583
33.0k
                           {V, Value::getConstInt(Int1Ty, 1)});
1584
33.0k
  }
1585
1586
5.67k
  Value getConstrainedFPRounding() noexcept {
1587
5.67k
    using namespace std::literals;
1588
5.67k
    auto Ctx = getCtx();
1589
5.67k
    auto RoundingStr = "round.tonearest"sv;
1590
5.67k
    auto RoundingMDS =
1591
5.67k
        LLVMMDStringInContext2(Ctx, RoundingStr.data(), RoundingStr.size());
1592
5.67k
    return LLVMMetadataAsValue(Ctx, RoundingMDS);
1593
5.67k
  }
1594
6.30k
  Value getConstrainedFPExcept() noexcept {
1595
6.30k
    using namespace std::literals;
1596
6.30k
    auto Ctx = getCtx();
1597
6.30k
    auto ExceptStr = "fpexcept.strict"sv;
1598
6.30k
    auto ExceptMDS =
1599
6.30k
        LLVMMDStringInContext2(Ctx, ExceptStr.data(), ExceptStr.size());
1600
6.30k
    return LLVMMetadataAsValue(Ctx, ExceptMDS);
1601
6.30k
  }
1602
1603
1.90k
  Value createArray(size_t Num, uint32_t Align) noexcept {
1604
1.90k
    Value Size = Value::getConstInt(LLVMInt64TypeInContext(getCtx()),
1605
1.90k
                                    static_cast<uint64_t>(Num) * Align);
1606
1.90k
    Type Int8Ty = LLVMInt8TypeInContext(getCtx());
1607
1.90k
    if (Num > 0) {
1608
1.15k
      auto Arr = createArrayAlloca(Int8Ty, Size);
1609
1.15k
      Arr.setAlignment(Align);
1610
1.15k
      return Arr;
1611
1.15k
    }
1612
748
    return Value::getConstPointerNull(Int8Ty.getPointerTo());
1613
1.90k
  }
1614
1615
  Value createValuePtrLoad(Type Ty, Value Ptr, Type PtrTy, uint64_t Idx0 = 0,
1616
4.69k
                           const char *Name = "") noexcept {
1617
4.69k
    auto VPtr = createConstInBoundsGEP1_64(PtrTy, Ptr, Idx0, Name);
1618
4.69k
    return createLoad(Ty, createBitCast(VPtr, Ty.getPointerTo()));
1619
4.69k
  }
1620
1621
  void createValuePtrStore(Value V, Value Ptr, Type PtrTy, uint64_t Idx0 = 0,
1622
2.32k
                           const char *Name = "") noexcept {
1623
2.32k
    auto VPtr = createConstInBoundsGEP1_64(PtrTy, Ptr, Idx0, Name);
1624
2.32k
    createStore(V, createBitCast(VPtr, V.getType().getPointerTo(), Name));
1625
2.32k
  }
1626
1627
  std::vector<Value> createArrayPtrLoad(size_t RetSize, Type Ty, Value Ptr,
1628
                                        Type PtrTy, uint32_t Align = 1,
1629
46
                                        const char *Name = "") noexcept {
1630
46
    std::vector<Value> ValVec;
1631
46
    ValVec.reserve(RetSize);
1632
138
    for (size_t I = 0; I < RetSize; ++I) {
1633
92
      auto VPtr = createConstInBoundsGEP1_64(PtrTy, Ptr, I * Align, Name);
1634
92
      auto TargetTy = Ty.getStructElementType(static_cast<unsigned int>(I));
1635
92
      ValVec.push_back(
1636
92
          createLoad(TargetTy, createBitCast(VPtr, TargetTy.getPointerTo())));
1637
92
    }
1638
46
    return ValVec;
1639
46
  }
1640
1641
  void createArrayPtrStore(Span<const Value> Vals, Value Ptr, Type PtrTy,
1642
963
                           uint32_t Align = 1, const char *Name = "") noexcept {
1643
2.38k
    for (size_t I = 0; I < Vals.size(); ++I) {
1644
1.42k
      auto VPtr = createConstInBoundsGEP1_64(PtrTy, Ptr, I * Align, Name);
1645
1.42k
      auto Val = Vals[I];
1646
1.42k
      createStore(Val, createBitCast(VPtr, Val.getType().getPointerTo()), Name);
1647
1.42k
    }
1648
963
  }
1649
1650
private:
1651
  LLVMBuilderRef Ref = nullptr;
1652
};
1653
1654
class Target {
1655
public:
1656
1.97k
  constexpr Target() noexcept = default;
1657
0
  constexpr Target(LLVMTargetRef R) noexcept : Ref(R) {}
1658
  Target(const Target &) = delete;
1659
  Target &operator=(const Target &) = delete;
1660
0
  Target(Target &&M) noexcept : Target() { swap(*this, M); }
1661
0
  Target &operator=(Target &&M) noexcept {
1662
0
    swap(*this, M);
1663
0
    return *this;
1664
0
  }
1665
1666
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1667
3.94k
  constexpr auto &unwrap() noexcept { return Ref; }
1668
0
  friend void swap(Target &LHS, Target &RHS) noexcept {
1669
0
    using std::swap;
1670
0
    swap(LHS.Ref, RHS.Ref);
1671
0
  }
1672
1673
1.97k
  static std::pair<Target, Message> getFromTriple(const char *Triple) noexcept {
1674
1.97k
    std::pair<Target, Message> Result;
1675
1.97k
    LLVMGetTargetFromTriple(Triple, &Result.first.unwrap(),
1676
1.97k
                            &Result.second.unwrap());
1677
1.97k
    return Result;
1678
1.97k
  }
1679
1680
private:
1681
  LLVMTargetRef Ref = nullptr;
1682
};
1683
1684
#if LLVM_VERSION_MAJOR < 13
1685
class PassManager {
1686
public:
1687
  constexpr PassManager() noexcept = default;
1688
3.94k
  constexpr PassManager(LLVMPassManagerRef R) noexcept : Ref(R) {}
1689
  PassManager(const PassManager &) = delete;
1690
  PassManager &operator=(const PassManager &) = delete;
1691
0
  PassManager(PassManager &&M) noexcept : PassManager() { swap(*this, M); }
1692
0
  PassManager &operator=(PassManager &&M) noexcept {
1693
0
    swap(*this, M);
1694
0
    return *this;
1695
0
  }
1696
1697
3.94k
  ~PassManager() noexcept { LLVMDisposePassManager(Ref); }
1698
1699
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1700
0
  constexpr auto &unwrap() const noexcept { return Ref; }
1701
7.88k
  constexpr auto &unwrap() noexcept { return Ref; }
1702
0
  friend void swap(PassManager &LHS, PassManager &RHS) noexcept {
1703
0
    using std::swap;
1704
0
    swap(LHS.Ref, RHS.Ref);
1705
0
  }
1706
1707
1.97k
  static PassManager create() noexcept { return LLVMCreatePassManager(); }
1708
1709
1.97k
  static PassManager createForModule(Module &M) noexcept {
1710
1.97k
    return LLVMCreateFunctionPassManagerForModule(M.unwrap());
1711
1.97k
  }
1712
1713
0
  void addTailCallEliminationPass() noexcept {
1714
0
    LLVMAddTailCallEliminationPass(Ref);
1715
0
  }
1716
0
  void addAlwaysInlinerPass() noexcept { LLVMAddAlwaysInlinerPass(Ref); }
1717
1718
1.97k
  void initializeFunctionPassManager() noexcept {
1719
1.97k
    LLVMInitializeFunctionPassManager(Ref);
1720
1.97k
  }
1721
1.97k
  void finalizeFunctionPassManager() noexcept {
1722
1.97k
    LLVMFinalizeFunctionPassManager(Ref);
1723
1.97k
  }
1724
20.5k
  void runFunctionPassManager(Value F) noexcept {
1725
20.5k
    LLVMRunFunctionPassManager(Ref, F.unwrap());
1726
20.5k
  }
1727
1.97k
  void runPassManager(Module &M) noexcept {
1728
1.97k
    LLVMRunPassManager(Ref, M.unwrap());
1729
1.97k
  }
1730
1731
private:
1732
  LLVMPassManagerRef Ref = nullptr;
1733
};
1734
1735
class PassManagerBuilder {
1736
public:
1737
  constexpr PassManagerBuilder() noexcept = default;
1738
1.97k
  constexpr PassManagerBuilder(LLVMPassManagerBuilderRef R) noexcept : Ref(R) {}
1739
  PassManagerBuilder(const PassManagerBuilder &) = delete;
1740
  PassManagerBuilder &operator=(const PassManagerBuilder &) = delete;
1741
0
  PassManagerBuilder(PassManagerBuilder &&M) noexcept : PassManagerBuilder() {
1742
0
    swap(*this, M);
1743
0
  }
1744
0
  PassManagerBuilder &operator=(PassManagerBuilder &&M) noexcept {
1745
0
    swap(*this, M);
1746
0
    return *this;
1747
0
  }
1748
1749
1.97k
  ~PassManagerBuilder() noexcept { LLVMPassManagerBuilderDispose(Ref); }
1750
1751
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1752
0
  constexpr auto &unwrap() const noexcept { return Ref; }
1753
0
  constexpr auto &unwrap() noexcept { return Ref; }
1754
0
  friend void swap(PassManagerBuilder &LHS, PassManagerBuilder &RHS) noexcept {
1755
0
    using std::swap;
1756
0
    swap(LHS.Ref, RHS.Ref);
1757
0
  }
1758
1759
1.97k
  static PassManagerBuilder create() noexcept {
1760
1.97k
    return LLVMPassManagerBuilderCreate();
1761
1.97k
  }
1762
1.97k
  void setOptLevel(unsigned int OptLevel) noexcept {
1763
1.97k
    LLVMPassManagerBuilderSetOptLevel(Ref, OptLevel);
1764
1.97k
  }
1765
1.97k
  void setSizeLevel(unsigned int SizeLevel) noexcept {
1766
1.97k
    LLVMPassManagerBuilderSetSizeLevel(Ref, SizeLevel);
1767
1.97k
  }
1768
1.97k
  void populateFunctionPassManager(PassManager &P) noexcept {
1769
1.97k
    LLVMPassManagerBuilderPopulateFunctionPassManager(Ref, P.unwrap());
1770
1.97k
  }
1771
1.97k
  void populateModulePassManager(PassManager &P) noexcept {
1772
1.97k
    LLVMPassManagerBuilderPopulateModulePassManager(Ref, P.unwrap());
1773
1.97k
  }
1774
1775
private:
1776
  LLVMPassManagerBuilderRef Ref = nullptr;
1777
};
1778
#endif
1779
1780
class TargetMachine {
1781
public:
1782
1.97k
  constexpr TargetMachine() noexcept = default;
1783
1.97k
  constexpr TargetMachine(LLVMTargetMachineRef R) noexcept : Ref(R) {}
1784
  TargetMachine(const TargetMachine &) = delete;
1785
  TargetMachine &operator=(const TargetMachine &) = delete;
1786
0
  TargetMachine(TargetMachine &&M) noexcept : TargetMachine() {
1787
0
    swap(*this, M);
1788
0
  }
1789
1.97k
  TargetMachine &operator=(TargetMachine &&M) noexcept {
1790
1.97k
    swap(*this, M);
1791
1.97k
    return *this;
1792
1.97k
  }
1793
1794
3.94k
  ~TargetMachine() noexcept { LLVMDisposeTargetMachine(Ref); }
1795
1796
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1797
0
  constexpr auto &unwrap() const noexcept { return Ref; }
1798
0
  constexpr auto &unwrap() noexcept { return Ref; }
1799
1.97k
  friend void swap(TargetMachine &LHS, TargetMachine &RHS) noexcept {
1800
1.97k
    using std::swap;
1801
1.97k
    swap(LHS.Ref, RHS.Ref);
1802
1.97k
  }
1803
1804
  static TargetMachine create(Target &T, const char *Triple, const char *CPU,
1805
                              const char *Features, LLVMCodeGenOptLevel Level,
1806
                              LLVMRelocMode Reloc,
1807
1.97k
                              LLVMCodeModel CodeModel) noexcept {
1808
1.97k
    return LLVMCreateTargetMachine(T.unwrap(), Triple, CPU, Features, Level,
1809
1.97k
                                   Reloc, CodeModel);
1810
1.97k
  }
1811
1812
#if LLVM_VERSION_MAJOR < 13
1813
3.94k
  void addAnalysisPasses(PassManager &P) noexcept {
1814
3.94k
    LLVMAddAnalysisPasses(Ref, P.unwrap());
1815
3.94k
  }
1816
#endif
1817
1818
  std::pair<MemoryBuffer, Message>
1819
1.97k
  emitToMemoryBuffer(Module &M, LLVMCodeGenFileType CodeGen) noexcept {
1820
1.97k
    std::pair<MemoryBuffer, Message> Result;
1821
1.97k
    LLVMTargetMachineEmitToMemoryBuffer(Ref, M.unwrap(), CodeGen,
1822
1.97k
                                        &Result.second.unwrap(),
1823
1.97k
                                        &Result.first.unwrap());
1824
1.97k
    return Result;
1825
1.97k
  }
1826
1827
private:
1828
  LLVMTargetMachineRef Ref = nullptr;
1829
};
1830
1831
#if LLVM_VERSION_MAJOR >= 13
1832
class PassBuilderOptions {
1833
public:
1834
  constexpr PassBuilderOptions() noexcept = default;
1835
  constexpr PassBuilderOptions(LLVMPassBuilderOptionsRef R) noexcept : Ref(R) {}
1836
  PassBuilderOptions(const PassBuilderOptions &) = delete;
1837
  PassBuilderOptions &operator=(const PassBuilderOptions &) = delete;
1838
  PassBuilderOptions(PassBuilderOptions &&O) noexcept : PassBuilderOptions() {
1839
    swap(*this, O);
1840
  }
1841
  PassBuilderOptions &operator=(PassBuilderOptions &&O) noexcept {
1842
    swap(*this, O);
1843
    return *this;
1844
  }
1845
1846
  ~PassBuilderOptions() noexcept { LLVMDisposePassBuilderOptions(Ref); }
1847
1848
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1849
  constexpr auto &unwrap() noexcept { return Ref; }
1850
  friend void swap(PassBuilderOptions &LHS, PassBuilderOptions &RHS) noexcept {
1851
    using std::swap;
1852
    swap(LHS.Ref, RHS.Ref);
1853
  }
1854
1855
  static PassBuilderOptions create() noexcept {
1856
    return LLVMCreatePassBuilderOptions();
1857
  }
1858
1859
  void setVerifyEach(bool VerifyEach) noexcept {
1860
    LLVMPassBuilderOptionsSetVerifyEach(Ref, VerifyEach);
1861
  }
1862
1863
  void setDebugLogging(bool DebugLogging) noexcept {
1864
    LLVMPassBuilderOptionsSetDebugLogging(Ref, DebugLogging);
1865
  }
1866
1867
  void setLoopInterleaving(bool LoopInterleaving) noexcept {
1868
    LLVMPassBuilderOptionsSetLoopInterleaving(Ref, LoopInterleaving);
1869
  }
1870
1871
  void setLoopVectorization(bool LoopVectorization) noexcept {
1872
    LLVMPassBuilderOptionsSetLoopVectorization(Ref, LoopVectorization);
1873
  }
1874
1875
  void setSLPVectorization(bool SLPVectorization) noexcept {
1876
    LLVMPassBuilderOptionsSetSLPVectorization(Ref, SLPVectorization);
1877
  }
1878
1879
  void setLoopUnrolling(bool LoopUnrolling) noexcept {
1880
    LLVMPassBuilderOptionsSetLoopUnrolling(Ref, LoopUnrolling);
1881
  }
1882
1883
  void setForgetAllSCEVInLoopUnroll(bool ForgetAllSCEVInLoopUnroll) noexcept {
1884
    LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(
1885
        Ref, ForgetAllSCEVInLoopUnroll);
1886
  }
1887
1888
  void setLicmMssaOptCap(unsigned int LicmMssaOptCap) noexcept {
1889
    LLVMPassBuilderOptionsSetLicmMssaOptCap(Ref, LicmMssaOptCap);
1890
  }
1891
1892
  void setLicmMssaNoAccForPromotionCap(
1893
      unsigned int LicmMssaNoAccForPromotionCap) noexcept {
1894
    LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(
1895
        Ref, LicmMssaNoAccForPromotionCap);
1896
  }
1897
1898
  void setCallGraphProfile(bool CallGraphProfile) noexcept {
1899
    LLVMPassBuilderOptionsSetCallGraphProfile(Ref, CallGraphProfile);
1900
  }
1901
1902
  void setMergeFunctions(bool MergeFunctions) noexcept {
1903
    LLVMPassBuilderOptionsSetMergeFunctions(Ref, MergeFunctions);
1904
  }
1905
1906
  Error runPasses(Module &M, const char *Passes,
1907
                  const TargetMachine &TM = nullptr) noexcept {
1908
    return LLVMRunPasses(M.unwrap(), Passes, TM.unwrap(), Ref);
1909
  }
1910
1911
private:
1912
  LLVMPassBuilderOptionsRef Ref = nullptr;
1913
};
1914
#endif
1915
1916
class SectionIterator {
1917
public:
1918
  constexpr SectionIterator() noexcept = default;
1919
3.94k
  constexpr SectionIterator(LLVMSectionIteratorRef R) noexcept : Ref(R) {}
1920
  SectionIterator(const SectionIterator &) = delete;
1921
  SectionIterator &operator=(const SectionIterator &) = delete;
1922
0
  SectionIterator(SectionIterator &&B) noexcept : SectionIterator() {
1923
0
    swap(*this, B);
1924
0
  }
1925
0
  SectionIterator &operator=(SectionIterator &&B) noexcept {
1926
0
    swap(*this, B);
1927
0
    return *this;
1928
0
  }
1929
1930
3.94k
  ~SectionIterator() noexcept { LLVMDisposeSectionIterator(Ref); }
1931
1932
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1933
62.4k
  constexpr auto &unwrap() const noexcept { return Ref; }
1934
0
  constexpr auto &unwrap() noexcept { return Ref; }
1935
0
  friend void swap(SectionIterator &LHS, SectionIterator &RHS) noexcept {
1936
0
    using std::swap;
1937
0
    swap(LHS.Ref, RHS.Ref);
1938
0
  }
1939
1940
58.5k
  void next() const noexcept { LLVMMoveToNextSection(Ref); }
1941
1942
54.5k
  const char *getName() const noexcept { return LLVMGetSectionName(Ref); }
1943
9.54k
  uint64_t getAddress() const noexcept { return LLVMGetSectionAddress(Ref); }
1944
58.5k
  uint64_t getSize() const noexcept { return LLVMGetSectionSize(Ref); }
1945
27.2k
  Span<const uint8_t> getContents() const noexcept {
1946
27.2k
    return {reinterpret_cast<const uint8_t *>(LLVMGetSectionContents(Ref)),
1947
27.2k
            static_cast<size_t>(LLVMGetSectionSize(Ref))};
1948
27.2k
  }
1949
1950
  inline bool isText() const noexcept;
1951
  inline bool isData() const noexcept;
1952
  inline bool isBSS() const noexcept;
1953
  inline bool isPData() const noexcept;
1954
  inline bool isEHFrame() const noexcept;
1955
1956
private:
1957
  LLVMSectionIteratorRef Ref = nullptr;
1958
};
1959
1960
class SymbolIterator {
1961
public:
1962
  constexpr SymbolIterator() noexcept = default;
1963
1.97k
  constexpr SymbolIterator(LLVMSymbolIteratorRef R) noexcept : Ref(R) {}
1964
  SymbolIterator(const SymbolIterator &) = delete;
1965
  SymbolIterator &operator=(const SymbolIterator &) = delete;
1966
0
  SymbolIterator(SymbolIterator &&B) noexcept : SymbolIterator() {
1967
0
    swap(*this, B);
1968
0
  }
1969
0
  SymbolIterator &operator=(SymbolIterator &&B) noexcept {
1970
0
    swap(*this, B);
1971
0
    return *this;
1972
0
  }
1973
1974
1.97k
  ~SymbolIterator() noexcept { LLVMDisposeSymbolIterator(Ref); }
1975
1976
22.2k
  constexpr operator bool() const noexcept { return Ref != nullptr; }
1977
22.2k
  constexpr auto &unwrap() const noexcept { return Ref; }
1978
0
  constexpr auto &unwrap() noexcept { return Ref; }
1979
0
  friend void swap(SymbolIterator &LHS, SymbolIterator &RHS) noexcept {
1980
0
    using std::swap;
1981
0
    swap(LHS.Ref, RHS.Ref);
1982
0
  }
1983
1984
20.3k
  void next() const noexcept { LLVMMoveToNextSymbol(Ref); }
1985
1986
20.3k
  const char *getName() const noexcept { return LLVMGetSymbolName(Ref); }
1987
20.3k
  uint64_t getAddress() const noexcept { return LLVMGetSymbolAddress(Ref); }
1988
0
  uint64_t getSize() const noexcept { return LLVMGetSymbolSize(Ref); }
1989
1990
private:
1991
  LLVMSymbolIteratorRef Ref = nullptr;
1992
};
1993
1994
class Binary {
1995
public:
1996
3.94k
  constexpr Binary() noexcept = default;
1997
1.97k
  constexpr Binary(LLVMBinaryRef R) noexcept : Ref(R) {}
1998
  Binary(const Binary &) = delete;
1999
  Binary &operator=(const Binary &) = delete;
2000
0
  Binary(Binary &&B) noexcept : Binary() { swap(*this, B); }
2001
3.94k
  Binary &operator=(Binary &&B) noexcept {
2002
3.94k
    swap(*this, B);
2003
3.94k
    return *this;
2004
3.94k
  }
2005
2006
5.91k
  ~Binary() noexcept { LLVMDisposeBinary(Ref); }
2007
2008
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2009
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2010
0
  constexpr auto &unwrap() noexcept { return Ref; }
2011
3.94k
  friend void swap(Binary &LHS, Binary &RHS) noexcept {
2012
3.94k
    using std::swap;
2013
3.94k
    swap(LHS.Ref, RHS.Ref);
2014
3.94k
  }
2015
2016
  static std::pair<Binary, Message> create(MemoryBuffer &M,
2017
1.97k
                                           Context &C) noexcept {
2018
1.97k
    std::pair<Binary, Message> Result;
2019
1.97k
    Result.first =
2020
1.97k
        LLVMCreateBinary(M.unwrap(), C.unwrap(), &Result.second.unwrap());
2021
1.97k
    return Result;
2022
1.97k
  }
2023
2024
0
  LLVMBinaryType getType() const noexcept { return LLVMBinaryGetType(Ref); }
2025
3.94k
  SectionIterator sections() const noexcept {
2026
3.94k
    return LLVMObjectFileCopySectionIterator(Ref);
2027
3.94k
  }
2028
62.4k
  bool isSectionEnd(const SectionIterator &It) const noexcept {
2029
62.4k
    return LLVMObjectFileIsSectionIteratorAtEnd(Ref, It.unwrap());
2030
62.4k
  }
2031
1.97k
  SymbolIterator symbols() const noexcept {
2032
1.97k
    return LLVMObjectFileCopySymbolIterator(Ref);
2033
1.97k
  }
2034
22.2k
  bool isSymbolEnd(const SymbolIterator &It) const noexcept {
2035
22.2k
    return LLVMObjectFileIsSymbolIteratorAtEnd(Ref, It.unwrap());
2036
22.2k
  }
2037
2038
private:
2039
  LLVMBinaryRef Ref = nullptr;
2040
};
2041
2042
class OrcThreadSafeContext {
2043
public:
2044
  constexpr OrcThreadSafeContext(LLVMOrcThreadSafeContextRef R) noexcept
2045
0
      : Ref(R) {}
2046
  OrcThreadSafeContext(const OrcThreadSafeContext &) = delete;
2047
  OrcThreadSafeContext &operator=(const OrcThreadSafeContext &) = delete;
2048
  OrcThreadSafeContext(OrcThreadSafeContext &&B) noexcept
2049
0
      : OrcThreadSafeContext() {
2050
0
    swap(*this, B);
2051
0
  }
2052
0
  OrcThreadSafeContext &operator=(OrcThreadSafeContext &&B) noexcept {
2053
0
    swap(*this, B);
2054
0
    return *this;
2055
0
  }
2056
2057
1.97k
  OrcThreadSafeContext() noexcept : Ref(LLVMOrcCreateNewThreadSafeContext()) {}
2058
1.97k
  ~OrcThreadSafeContext() noexcept { LLVMOrcDisposeThreadSafeContext(Ref); }
2059
2060
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2061
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2062
0
  constexpr auto &unwrap() noexcept { return Ref; }
2063
0
  LLVMOrcThreadSafeContextRef release() noexcept {
2064
0
    return std::exchange(Ref, nullptr);
2065
0
  }
2066
  friend void swap(OrcThreadSafeContext &LHS,
2067
0
                   OrcThreadSafeContext &RHS) noexcept {
2068
0
    using std::swap;
2069
0
    swap(LHS.Ref, RHS.Ref);
2070
0
  }
2071
2072
5.91k
  Context getContext() noexcept {
2073
5.91k
    return LLVMOrcThreadSafeContextGetContext(Ref);
2074
5.91k
  }
2075
2076
private:
2077
  LLVMOrcThreadSafeContextRef Ref = nullptr;
2078
};
2079
2080
class OrcThreadSafeModule {
2081
public:
2082
  constexpr OrcThreadSafeModule() noexcept = default;
2083
  constexpr OrcThreadSafeModule(LLVMOrcThreadSafeModuleRef R) noexcept
2084
0
      : Ref(R) {}
2085
  OrcThreadSafeModule(const OrcThreadSafeModule &) = delete;
2086
  OrcThreadSafeModule &operator=(const OrcThreadSafeModule &) = delete;
2087
  OrcThreadSafeModule(OrcThreadSafeModule &&B) noexcept
2088
0
      : OrcThreadSafeModule() {
2089
0
    swap(*this, B);
2090
0
  }
2091
0
  OrcThreadSafeModule &operator=(OrcThreadSafeModule &&B) noexcept {
2092
0
    swap(*this, B);
2093
0
    return *this;
2094
0
  }
2095
2096
  OrcThreadSafeModule(Module &&M, OrcThreadSafeContext &C) noexcept
2097
0
      : Ref(LLVMOrcCreateNewThreadSafeModule(M.release(), C.unwrap())) {}
2098
0
  ~OrcThreadSafeModule() noexcept { LLVMOrcDisposeThreadSafeModule(Ref); }
2099
2100
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2101
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2102
0
  constexpr auto &unwrap() noexcept { return Ref; }
2103
0
  LLVMOrcThreadSafeModuleRef release() noexcept {
2104
0
    return std::exchange(Ref, nullptr);
2105
0
  }
2106
  friend void swap(OrcThreadSafeModule &LHS,
2107
0
                   OrcThreadSafeModule &RHS) noexcept {
2108
0
    using std::swap;
2109
0
    swap(LHS.Ref, RHS.Ref);
2110
0
  }
2111
  Error withModuleDo(LLVMOrcGenericIRModuleOperationFunction F,
2112
0
                     void *Ctx) noexcept {
2113
0
    return LLVMOrcThreadSafeModuleWithModuleDo(Ref, F, Ctx);
2114
0
  }
2115
2116
private:
2117
  LLVMOrcThreadSafeModuleRef Ref = nullptr;
2118
};
2119
2120
class OrcJITDylib {
2121
public:
2122
  constexpr OrcJITDylib() noexcept = default;
2123
0
  constexpr OrcJITDylib(LLVMOrcJITDylibRef R) noexcept : Ref(R) {}
2124
  OrcJITDylib(const OrcJITDylib &) = delete;
2125
  OrcJITDylib &operator=(const OrcJITDylib &) = delete;
2126
0
  OrcJITDylib(OrcJITDylib &&B) noexcept : OrcJITDylib() { swap(*this, B); }
2127
0
  OrcJITDylib &operator=(OrcJITDylib &&B) noexcept {
2128
0
    swap(*this, B);
2129
0
    return *this;
2130
0
  }
2131
2132
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2133
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2134
0
  constexpr auto &unwrap() noexcept { return Ref; }
2135
0
  friend void swap(OrcJITDylib &LHS, OrcJITDylib &RHS) noexcept {
2136
0
    using std::swap;
2137
0
    swap(LHS.Ref, RHS.Ref);
2138
0
  }
2139
2140
private:
2141
  LLVMOrcJITDylibRef Ref = nullptr;
2142
};
2143
2144
class OrcIRTransformLayer {
2145
public:
2146
  constexpr OrcIRTransformLayer() noexcept = default;
2147
  constexpr OrcIRTransformLayer(LLVMOrcIRTransformLayerRef R) noexcept
2148
0
      : Ref(R) {}
2149
  OrcIRTransformLayer(const OrcIRTransformLayer &) = delete;
2150
  OrcIRTransformLayer &operator=(const OrcIRTransformLayer &) = delete;
2151
  OrcIRTransformLayer(OrcIRTransformLayer &&B) noexcept
2152
0
      : OrcIRTransformLayer() {
2153
0
    swap(*this, B);
2154
0
  }
2155
0
  OrcIRTransformLayer &operator=(OrcIRTransformLayer &&B) noexcept {
2156
0
    swap(*this, B);
2157
0
    return *this;
2158
0
  }
2159
2160
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2161
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2162
0
  constexpr auto &unwrap() noexcept { return Ref; }
2163
  friend void swap(OrcIRTransformLayer &LHS,
2164
0
                   OrcIRTransformLayer &RHS) noexcept {
2165
0
    using std::swap;
2166
0
    swap(LHS.Ref, RHS.Ref);
2167
0
  }
2168
2169
  void setTransform(LLVMOrcIRTransformLayerTransformFunction TransformFunction,
2170
0
                    void *Ctx) noexcept {
2171
0
    LLVMOrcIRTransformLayerSetTransform(Ref, TransformFunction, Ctx);
2172
0
  }
2173
2174
private:
2175
  LLVMOrcIRTransformLayerRef Ref = nullptr;
2176
};
2177
2178
class OrcLLJIT {
2179
public:
2180
0
  constexpr OrcLLJIT() noexcept = default;
2181
0
  constexpr OrcLLJIT(LLVMOrcLLJITRef R) noexcept : Ref(R) {}
2182
  OrcLLJIT(const OrcLLJIT &) = delete;
2183
  OrcLLJIT &operator=(const OrcLLJIT &) = delete;
2184
0
  OrcLLJIT(OrcLLJIT &&B) noexcept : OrcLLJIT() { swap(*this, B); }
2185
0
  OrcLLJIT &operator=(OrcLLJIT &&B) noexcept {
2186
0
    swap(*this, B);
2187
0
    return *this;
2188
0
  }
2189
2190
0
  ~OrcLLJIT() noexcept { LLVMOrcDisposeLLJIT(Ref); }
2191
2192
0
  constexpr operator bool() const noexcept { return Ref != nullptr; }
2193
0
  constexpr auto &unwrap() const noexcept { return Ref; }
2194
0
  constexpr auto &unwrap() noexcept { return Ref; }
2195
0
  friend void swap(OrcLLJIT &LHS, OrcLLJIT &RHS) noexcept {
2196
0
    using std::swap;
2197
0
    swap(LHS.Ref, RHS.Ref);
2198
0
  }
2199
2200
0
  static cxx20::expected<OrcLLJIT, Error> create() noexcept {
2201
0
    OrcLLJIT Result;
2202
0
    if (auto Err = LLVMOrcCreateLLJIT(&Result.Ref, getBuilder())) {
2203
0
      return cxx20::unexpected(Err);
2204
0
    } else {
2205
0
      return Result;
2206
0
    }
2207
0
  }
2208
2209
0
  OrcJITDylib getMainJITDylib() noexcept {
2210
0
    return LLVMOrcLLJITGetMainJITDylib(Ref);
2211
0
  }
2212
2213
0
  Error addLLVMIRModule(const OrcJITDylib &L, OrcThreadSafeModule M) noexcept {
2214
0
    return LLVMOrcLLJITAddLLVMIRModule(Ref, L.unwrap(), M.release());
2215
0
  }
2216
2217
  template <typename T>
2218
0
  cxx20::expected<T *, Error> lookup(const char *Name) noexcept {
2219
0
    LLVMOrcJITTargetAddress Addr;
2220
0
    if (auto Err = LLVMOrcLLJITLookup(Ref, &Addr, Name)) {
2221
0
      return cxx20::unexpected(Err);
2222
0
    }
2223
0
    return reinterpret_cast<T *>(Addr);
2224
0
  }
Unexecuted instantiation: cxx20::expected<void* const (**) [38], WasmEdge::LLVM::Error> WasmEdge::LLVM::OrcLLJIT::lookup<void* const (*) [38]>(char const*)
Unexecuted instantiation: cxx20::expected<void (*)(void*, void*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*), WasmEdge::LLVM::Error> WasmEdge::LLVM::OrcLLJIT::lookup<void (void*, void*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)>(char const*)
Unexecuted instantiation: cxx20::expected<void*, WasmEdge::LLVM::Error> WasmEdge::LLVM::OrcLLJIT::lookup<void>(char const*)
2225
2226
0
  OrcIRTransformLayer getIRTransformLayer() noexcept {
2227
0
    return LLVMOrcLLJITGetIRTransformLayer(Ref);
2228
0
  }
2229
2230
private:
2231
  LLVMOrcLLJITRef Ref = nullptr;
2232
2233
  static inline LLVMOrcLLJITBuilderRef getBuilder() noexcept;
2234
};
2235
2236
} // namespace WasmEdge::LLVM
2237
2238
#include <llvm/IR/GlobalValue.h>
2239
#include <llvm/Object/ObjectFile.h>
2240
#include <llvm/Transforms/Utils/BasicBlockUtils.h>
2241
#if LLVM_VERSION_MAJOR < 12 || WASMEDGE_OS_WINDOWS
2242
#include <llvm/ExecutionEngine/Orc/Core.h>
2243
#endif
2244
#if LLVM_VERSION_MAJOR < 13
2245
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
2246
#include <llvm/Support/CBindingWrapping.h>
2247
#include <llvm/Support/Error.h>
2248
#endif
2249
2250
#if WASMEDGE_OS_WINDOWS
2251
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
2252
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
2253
#include <llvm/Support/Process.h>
2254
#include <system/winapi.h>
2255
#endif
2256
2257
namespace llvm {
2258
#if WASMEDGE_OS_WINDOWS
2259
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession,
2260
                                   LLVMOrcExecutionSessionRef)
2261
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ObjectLayer, LLVMOrcObjectLayerRef)
2262
#endif
2263
#if LLVM_VERSION_MAJOR < 12
2264
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJITBuilder, LLVMOrcLLJITBuilderRef)
2265
#endif
2266
#if LLVM_VERSION_MAJOR < 13
2267
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeModule,
2268
                                   LLVMOrcThreadSafeModuleRef)
2269
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRTransformLayer,
2270
                                   LLVMOrcIRTransformLayerRef)
2271
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility,
2272
                                   LLVMOrcMaterializationResponsibilityRef)
2273
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJIT, LLVMOrcLLJITRef)
2274
#endif
2275
} // namespace llvm
2276
2277
namespace WasmEdge::LLVM {
2278
2279
20.6k
void Value::setDSOLocal(bool Local) noexcept {
2280
20.6k
  llvm::cast<llvm::GlobalValue>(reinterpret_cast<llvm::Value *>(Ref))
2281
20.6k
      ->setDSOLocal(Local);
2282
20.6k
}
2283
2284
10.5k
void Value::eliminateUnreachableBlocks() noexcept {
2285
10.5k
  llvm::EliminateUnreachableBlocks(
2286
10.5k
      *llvm::cast<llvm::Function>(reinterpret_cast<llvm::Value *>(Ref)));
2287
10.5k
}
2288
2289
50.8k
bool SectionIterator::isText() const noexcept {
2290
50.8k
  auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref);
2291
50.8k
  return (*S)->isText();
2292
50.8k
}
2293
2294
47.1k
bool SectionIterator::isData() const noexcept {
2295
47.1k
  auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref);
2296
47.1k
  return (*S)->isData();
2297
47.1k
}
2298
2299
39.4k
bool SectionIterator::isBSS() const noexcept {
2300
39.4k
  auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref);
2301
39.4k
  return (*S)->isBSS();
2302
39.4k
}
2303
2304
50.8k
bool SectionIterator::isPData() const noexcept {
2305
#if WASMEDGE_OS_WINDOWS
2306
  using namespace std::literals;
2307
  return ".pdata"sv == getName();
2308
#else
2309
50.8k
  return false;
2310
50.8k
#endif
2311
50.8k
}
2312
2313
54.5k
bool SectionIterator::isEHFrame() const noexcept {
2314
54.5k
#if WASMEDGE_OS_LINUX
2315
54.5k
  using namespace std::literals;
2316
54.5k
  return ".eh_frame"sv == getName();
2317
#elif WASMEDGE_OS_MACOS
2318
  using namespace std::literals;
2319
  return "__eh_frame"sv == getName();
2320
#else
2321
  return false;
2322
#endif
2323
54.5k
}
2324
2325
#if WASMEDGE_OS_WINDOWS
2326
class DefaultMMapper final : public llvm::SectionMemoryManager::MemoryMapper {
2327
public:
2328
  llvm::sys::MemoryBlock allocateMappedMemory(
2329
      llvm::SectionMemoryManager::AllocationPurpose /*Purpose*/,
2330
      size_t NumBytes, const llvm::sys::MemoryBlock *const NearBlock,
2331
      unsigned Flags, std::error_code &EC) override {
2332
    return llvm::sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags,
2333
                                                   EC);
2334
  }
2335
  std::error_code protectMappedMemory(const llvm::sys::MemoryBlock &Block,
2336
                                      unsigned Flags) override {
2337
    return llvm::sys::Memory::protectMappedMemory(Block, Flags);
2338
  }
2339
2340
  std::error_code releaseMappedMemory(llvm::sys::MemoryBlock &M) override {
2341
    return llvm::sys::Memory::releaseMappedMemory(M);
2342
  }
2343
};
2344
2345
class ContiguousSectionMemoryManager : public llvm::RTDyldMemoryManager {
2346
public:
2347
  explicit ContiguousSectionMemoryManager(
2348
      llvm::SectionMemoryManager::MemoryMapper *UnownedMM = nullptr)
2349
      : MMapper(UnownedMM), OwnedMMapper(nullptr) {
2350
    if (!MMapper) {
2351
      OwnedMMapper = std::make_unique<DefaultMMapper>();
2352
      MMapper = OwnedMMapper.get();
2353
    }
2354
  }
2355
2356
  ~ContiguousSectionMemoryManager() noexcept override {
2357
    using namespace std::literals;
2358
    if (Preallocated.allocatedSize() != 0) {
2359
      auto EC = MMapper->releaseMappedMemory(Preallocated);
2360
      if (EC) {
2361
        spdlog::error("releaseMappedMemory failed with error: {}"sv,
2362
                      EC.message());
2363
      }
2364
    }
2365
  }
2366
2367
  bool needsToReserveAllocationSpace() override { return true; }
2368
2369
  void reserveAllocationSpace(uintptr_t CodeSize, llvm::Align CodeAlign,
2370
                              uintptr_t RODataSize, llvm::Align RODataAlign,
2371
                              uintptr_t RWDataSize,
2372
                              llvm::Align RWDataAlign) override {
2373
    using namespace std::literals;
2374
    assuming(Preallocated.allocatedSize() == 0);
2375
2376
    static const size_t PageSize = llvm::sys::Process::getPageSizeEstimate();
2377
    assuming(CodeAlign.value() <= PageSize);
2378
    assuming(RODataAlign.value() <= PageSize);
2379
    assuming(RWDataAlign.value() <= PageSize);
2380
    CodeSize = roundUpTo(CodeSize + CodeAlign.value(), PageSize);
2381
    RODataSize = roundUpTo(RODataSize + RODataAlign.value(), PageSize);
2382
    RWDataSize = roundUpTo(RWDataSize + RWDataAlign.value(), PageSize);
2383
    const uintptr_t TotalSize =
2384
        CodeSize + RODataSize + RWDataSize + PageSize * 3;
2385
2386
    std::error_code EC;
2387
    Preallocated = MMapper->allocateMappedMemory(
2388
        llvm::SectionMemoryManager::AllocationPurpose::Code, TotalSize, nullptr,
2389
        llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE, EC);
2390
    if (EC) {
2391
      spdlog::error("allocateMappedMemory failed with error: {}"sv,
2392
                    EC.message());
2393
      return;
2394
    }
2395
2396
    auto base = reinterpret_cast<std::uintptr_t>(Preallocated.base());
2397
    CodeMem = CodeFree =
2398
        llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), CodeSize);
2399
    base += CodeSize;
2400
    RODataMem = RODataFree =
2401
        llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), RODataSize);
2402
    base += RODataSize;
2403
    RWDataMem = RWDataFree =
2404
        llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), RWDataSize);
2405
  }
2406
2407
  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
2408
                               unsigned /*SectionID*/,
2409
                               llvm::StringRef /*SectionName*/,
2410
                               bool IsReadOnly) override {
2411
    if (IsReadOnly) {
2412
      return Allocate(RODataFree, Size, Alignment);
2413
    } else {
2414
      return Allocate(RWDataFree, Size, Alignment);
2415
    }
2416
  }
2417
2418
  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
2419
                               unsigned /*SectionID*/,
2420
                               llvm::StringRef /*SectionName*/) override {
2421
    return Allocate(CodeFree, Size, Alignment);
2422
  }
2423
2424
  bool finalizeMemory(std::string *ErrMsg) override {
2425
    std::error_code EC;
2426
2427
    EC = MMapper->protectMappedMemory(CodeMem, llvm::sys::Memory::MF_READ |
2428
                                                   llvm::sys::Memory::MF_EXEC);
2429
    if (EC) {
2430
      if (ErrMsg) {
2431
        *ErrMsg = EC.message();
2432
      }
2433
      return true;
2434
    }
2435
    EC = MMapper->protectMappedMemory(RODataMem, llvm::sys::Memory::MF_READ);
2436
    if (EC) {
2437
      if (ErrMsg) {
2438
        *ErrMsg = EC.message();
2439
      }
2440
      return true;
2441
    }
2442
2443
    llvm::sys::Memory::InvalidateInstructionCache(CodeMem.base(),
2444
                                                  CodeMem.allocatedSize());
2445
    return false;
2446
  }
2447
2448
private:
2449
  llvm::sys::MemoryBlock Preallocated;
2450
2451
  // Sections must be in the order code < rodata < rwdata.
2452
  llvm::sys::MemoryBlock CodeMem;
2453
  llvm::sys::MemoryBlock RODataMem;
2454
  llvm::sys::MemoryBlock RWDataMem;
2455
2456
  llvm::sys::MemoryBlock CodeFree;
2457
  llvm::sys::MemoryBlock RODataFree;
2458
  llvm::sys::MemoryBlock RWDataFree;
2459
2460
  llvm::SectionMemoryManager::MemoryMapper *MMapper;
2461
  std::unique_ptr<llvm::SectionMemoryManager::MemoryMapper> OwnedMMapper;
2462
2463
  uint8_t *Allocate(llvm::sys::MemoryBlock &FreeBlock, std::uintptr_t Size,
2464
                    unsigned alignment) {
2465
    using namespace std::literals;
2466
    const auto Base = reinterpret_cast<uintptr_t>(FreeBlock.base());
2467
    const auto Start = roundUpTo(Base, alignment);
2468
    const uintptr_t PaddedSize = (Start - Base) + Size;
2469
    if (PaddedSize > FreeBlock.allocatedSize()) {
2470
      spdlog::error("Failed to satisfy suballocation request for {}"sv, Size);
2471
      return nullptr;
2472
    }
2473
    FreeBlock =
2474
        llvm::sys::MemoryBlock(reinterpret_cast<void *>(Base + PaddedSize),
2475
                               FreeBlock.allocatedSize() - PaddedSize);
2476
    return reinterpret_cast<uint8_t *>(Start);
2477
  }
2478
2479
  static uintptr_t roundUpTo(uintptr_t Value, uintptr_t Divisor) noexcept {
2480
    return ((Value + (Divisor - 1)) / Divisor) * Divisor;
2481
  }
2482
};
2483
2484
// Register stack unwind info for JIT functions
2485
class Win64EHManager : public ContiguousSectionMemoryManager {
2486
  using Base = ContiguousSectionMemoryManager;
2487
  uint64_t CodeAddress = 0;
2488
2489
public:
2490
  ~Win64EHManager() noexcept override {}
2491
2492
  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
2493
                               unsigned SectionID,
2494
                               llvm::StringRef SectionName) override {
2495
    using namespace std::literals;
2496
    const auto Allocated =
2497
        Base::allocateCodeSection(Size, Alignment, SectionID, SectionName);
2498
    if (SectionName == llvm::StringRef(".text"sv)) {
2499
      CodeAddress = reinterpret_cast<uint64_t>(Allocated);
2500
    }
2501
    return Allocated;
2502
  }
2503
2504
  void registerEHFrames(uint8_t *Addr, uint64_t /*LoadAddr*/,
2505
                        size_t Size) noexcept override {
2506
    using namespace std::literals;
2507
    winapi::RUNTIME_FUNCTION_ *const FunctionTable =
2508
        reinterpret_cast<winapi::RUNTIME_FUNCTION_ *>(Addr);
2509
    const uint32_t EntryCount =
2510
        static_cast<uint32_t>(Size / sizeof(winapi::RUNTIME_FUNCTION_));
2511
    if (EntryCount == 0)
2512
      return;
2513
    // Calculate object image base address by assuming that address of the first
2514
    // function is equal to the address of the code section
2515
    const auto ImageBase = CodeAddress - FunctionTable[0].BeginAddress;
2516
    winapi::RtlAddFunctionTable(FunctionTable, EntryCount, ImageBase);
2517
    EHFrames.push_back({Addr, Size});
2518
  }
2519
  void deregisterEHFrames() noexcept override {
2520
    using namespace std::literals;
2521
    for (auto &Frame : EHFrames) {
2522
      winapi::RtlDeleteFunctionTable(
2523
          reinterpret_cast<winapi::RUNTIME_FUNCTION_ *>(Frame.Addr));
2524
    }
2525
    EHFrames.clear();
2526
  }
2527
};
2528
2529
LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept {
2530
  using llvm::unwrap;
2531
  using llvm::wrap;
2532
  const LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder();
2533
  LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(
2534
      Builder,
2535
      [](void *, LLVMOrcExecutionSessionRef ES, const char *) noexcept {
2536
        auto Layer = std::make_unique<llvm::orc::RTDyldObjectLinkingLayer>(
2537
            *unwrap(ES), []() { return std::make_unique<Win64EHManager>(); });
2538
        Layer->setOverrideObjectFlagsWithResponsibilityFlags(true);
2539
        Layer->setAutoClaimResponsibilityForObjectSymbols(true);
2540
        return wrap(static_cast<llvm::orc::ObjectLayer *>(Layer.release()));
2541
      },
2542
      nullptr);
2543
  return Builder;
2544
}
2545
#else
2546
0
LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { return nullptr; }
2547
#endif
2548
2549
} // namespace WasmEdge::LLVM
2550
2551
#if LLVM_VERSION_MAJOR < 12 && WASMEDGE_OS_WINDOWS
2552
void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(
2553
    LLVMOrcLLJITBuilderRef Builder,
2554
    LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F,
2555
    void *Ctx) noexcept {
2556
  using llvm::unwrap;
2557
  using llvm::wrap;
2558
  unwrap(Builder)->setObjectLinkingLayerCreator(
2559
      [=](llvm::orc::ExecutionSession &ES, const llvm::Triple &TT) {
2560
        auto TTStr = TT.str();
2561
        return std::unique_ptr<llvm::orc::ObjectLayer>(
2562
            unwrap(F(Ctx, wrap(&ES), TTStr.c_str())));
2563
      });
2564
}
2565
#endif
2566
#if LLVM_VERSION_MAJOR < 13
2567
LLVMOrcIRTransformLayerRef
2568
0
LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept {
2569
0
  using llvm::unwrap;
2570
0
  using llvm::wrap;
2571
0
  return wrap(&(unwrap(J)->getIRTransformLayer()));
2572
0
}
Unexecuted instantiation: compiler.cpp:LLVMOrcLLJITGetIRTransformLayer(LLVMOrcOpaqueLLJIT*)
Unexecuted instantiation: codegen.cpp:LLVMOrcLLJITGetIRTransformLayer(LLVMOrcOpaqueLLJIT*)
Unexecuted instantiation: data.cpp:LLVMOrcLLJITGetIRTransformLayer(LLVMOrcOpaqueLLJIT*)
Unexecuted instantiation: jit.cpp:LLVMOrcLLJITGetIRTransformLayer(LLVMOrcOpaqueLLJIT*)
2573
void LLVMOrcIRTransformLayerSetTransform(
2574
    LLVMOrcIRTransformLayerRef IRTransformLayer,
2575
    LLVMOrcIRTransformLayerTransformFunction TransformFunction,
2576
0
    void *Ctx) noexcept {
2577
0
  using llvm::unwrap;
2578
0
  using llvm::wrap;
2579
0
  unwrap(IRTransformLayer)
2580
0
      ->setTransform([=](llvm::orc::ThreadSafeModule TSM,
2581
0
                         llvm::orc::MaterializationResponsibility &R)
2582
0
                         -> llvm::Expected<llvm::orc::ThreadSafeModule> {
2583
0
        LLVMOrcThreadSafeModuleRef TSMRef =
2584
0
            wrap(new llvm::orc::ThreadSafeModule(std::move(TSM)));
2585
0
        if (LLVMErrorRef Err = TransformFunction(Ctx, &TSMRef, wrap(&R))) {
2586
0
          return unwrap(Err);
2587
0
        }
2588
0
        return std::move(*unwrap(TSMRef));
2589
0
      });
2590
0
}
Unexecuted instantiation: compiler.cpp:LLVMOrcIRTransformLayerSetTransform(LLVMOrcOpaqueIRTransformLayer*, LLVMOpaqueError* (*)(void*, LLVMOrcOpaqueThreadSafeModule**, LLVMOrcOpaqueMaterializationResponsibility*) noexcept, void*)
Unexecuted instantiation: codegen.cpp:LLVMOrcIRTransformLayerSetTransform(LLVMOrcOpaqueIRTransformLayer*, LLVMOpaqueError* (*)(void*, LLVMOrcOpaqueThreadSafeModule**, LLVMOrcOpaqueMaterializationResponsibility*) noexcept, void*)
Unexecuted instantiation: data.cpp:LLVMOrcIRTransformLayerSetTransform(LLVMOrcOpaqueIRTransformLayer*, LLVMOpaqueError* (*)(void*, LLVMOrcOpaqueThreadSafeModule**, LLVMOrcOpaqueMaterializationResponsibility*) noexcept, void*)
Unexecuted instantiation: jit.cpp:LLVMOrcIRTransformLayerSetTransform(LLVMOrcOpaqueIRTransformLayer*, LLVMOpaqueError* (*)(void*, LLVMOrcOpaqueThreadSafeModule**, LLVMOrcOpaqueMaterializationResponsibility*) noexcept, void*)
2591
2592
LLVMErrorRef
2593
LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM,
2594
                                    LLVMOrcGenericIRModuleOperationFunction F,
2595
0
                                    void *Ctx) noexcept {
2596
0
  using llvm::unwrap;
2597
0
  using llvm::wrap;
2598
0
  return wrap(unwrap(TSM)->withModuleDo(
2599
0
      [&](llvm::Module &M) { return unwrap(F(Ctx, wrap(&M))); }));
2600
0
}
Unexecuted instantiation: compiler.cpp:LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcOpaqueThreadSafeModule*, LLVMOpaqueError* (*)(void*, LLVMOpaqueModule*) noexcept, void*)
Unexecuted instantiation: codegen.cpp:LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcOpaqueThreadSafeModule*, LLVMOpaqueError* (*)(void*, LLVMOpaqueModule*) noexcept, void*)
Unexecuted instantiation: data.cpp:LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcOpaqueThreadSafeModule*, LLVMOpaqueError* (*)(void*, LLVMOpaqueModule*) noexcept, void*)
Unexecuted instantiation: jit.cpp:LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcOpaqueThreadSafeModule*, LLVMOpaqueError* (*)(void*, LLVMOpaqueModule*) noexcept, void*)
2601
#endif