]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_llvm / llvm-wrapper / RustWrapper.cpp
CommitLineData
1b1a35ee 1#include "LLVMWrapper.h"
add651ee 2#include "llvm/ADT/Statistic.h"
cc61c64b 3#include "llvm/IR/DebugInfoMetadata.h"
a2a8927a 4#include "llvm/IR/DiagnosticHandler.h"
1a4d82fc
JJ
5#include "llvm/IR/DiagnosticInfo.h"
6#include "llvm/IR/DiagnosticPrinter.h"
b7449926 7#include "llvm/IR/GlobalVariable.h"
5bcae85e 8#include "llvm/IR/Instructions.h"
f035d41b 9#include "llvm/IR/Intrinsics.h"
064997fb 10#include "llvm/IR/IntrinsicsARM.h"
fe692bf9 11#include "llvm/IR/LLVMRemarkStreamer.h"
04454e1e 12#include "llvm/IR/Mangler.h"
c620b35d 13#include "llvm/IR/Value.h"
fe692bf9
FG
14#include "llvm/Remarks/RemarkStreamer.h"
15#include "llvm/Remarks/RemarkSerializer.h"
16#include "llvm/Remarks/RemarkFormat.h"
17#include "llvm/Support/ToolOutputFile.h"
487cf647 18#include "llvm/Support/ModRef.h"
32a655c1 19#include "llvm/Object/Archive.h"
17df50a5 20#include "llvm/Object/COFFImportFile.h"
32a655c1 21#include "llvm/Object/ObjectFile.h"
5e7ed085 22#include "llvm/Pass.h"
2b03887a 23#include "llvm/Bitcode/BitcodeWriter.h"
0bf4aa26 24#include "llvm/Support/Signals.h"
3b2f2976 25
0bf4aa26
XL
26#include <iostream>
27
e8be2606
FG
28// for raw `write` in the bad-alloc handler
29#ifdef _MSC_VER
30#include <io.h>
31#else
32#include <unistd.h>
33#endif
34
223e47cc
LB
35//===----------------------------------------------------------------------===
36//
37// This file defines alternate interfaces to core functions that are more
38// readily callable by Rust's FFI.
39//
40//===----------------------------------------------------------------------===
41
223e47cc
LB
42using namespace llvm;
43using namespace llvm::sys;
1a4d82fc 44using namespace llvm::object;
223e47cc 45
5bcae85e
SL
46// LLVMAtomicOrdering is already an enum - don't create another
47// one.
32a655c1 48static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
5bcae85e 49 switch (Ordering) {
32a655c1
SL
50 case LLVMAtomicOrderingNotAtomic:
51 return AtomicOrdering::NotAtomic;
52 case LLVMAtomicOrderingUnordered:
53 return AtomicOrdering::Unordered;
54 case LLVMAtomicOrderingMonotonic:
55 return AtomicOrdering::Monotonic;
56 case LLVMAtomicOrderingAcquire:
57 return AtomicOrdering::Acquire;
58 case LLVMAtomicOrderingRelease:
59 return AtomicOrdering::Release;
60 case LLVMAtomicOrderingAcquireRelease:
61 return AtomicOrdering::AcquireRelease;
62 case LLVMAtomicOrderingSequentiallyConsistent:
63 return AtomicOrdering::SequentiallyConsistent;
5bcae85e
SL
64 }
65
ff7c6d11 66 report_fatal_error("Invalid LLVMAtomicOrdering value!");
5bcae85e
SL
67}
68
abe05a73 69static LLVM_THREAD_LOCAL char *LastError;
970d7e83 70
0bf4aa26
XL
71// Custom error handler for fatal LLVM errors.
72//
73// Notably it exits the process with code 101, unlike LLVM's default of 1.
74static void FatalErrorHandler(void *UserData,
c295e0f8 75 const char* Reason,
0bf4aa26 76 bool GenCrashDiag) {
c620b35d
FG
77 // Once upon a time we emitted "LLVM ERROR:" specifically to mimic LLVM. Then,
78 // we developed crater and other tools which only expose logs, not error codes.
79 // Use a more greppable prefix that will still match the "LLVM ERROR:" prefix.
80 std::cerr << "rustc-LLVM ERROR: " << Reason << std::endl;
0bf4aa26
XL
81
82 // Since this error handler exits the process, we have to run any cleanup that
83 // LLVM would run after handling the error. This might change with an LLVM
84 // upgrade.
c620b35d
FG
85 //
86 // In practice, this will do nothing, because the only cleanup LLVM does is
87 // to remove all files that were registered with it via a frontend calling
88 // one of the `createOutputFile` family of functions in LLVM and passing true
89 // to RemoveFileOnSignal, something that rustc does not do. However, it would
90 // be... inadvisable to suddenly stop running these handlers, if LLVM gets
91 // "interesting" ideas in the future about what cleanup should be done.
92 // We might even find it useful for generating less artifacts.
0bf4aa26
XL
93 sys::RunInterruptHandlers();
94
95 exit(101);
96}
97
e8be2606
FG
98// Custom error handler for bad-alloc LLVM errors.
99//
100// It aborts the process without any further allocations, similar to LLVM's
101// default except that may be configured to `throw std::bad_alloc()` instead.
102static void BadAllocErrorHandler(void *UserData,
103 const char* Reason,
104 bool GenCrashDiag) {
105 const char *OOM = "rustc-LLVM ERROR: out of memory\n";
106 (void)!::write(2, OOM, strlen(OOM));
107 (void)!::write(2, Reason, strlen(Reason));
108 (void)!::write(2, "\n", 1);
109 abort();
110}
111
112extern "C" void LLVMRustInstallErrorHandlers() {
113 install_bad_alloc_error_handler(BadAllocErrorHandler);
0bf4aa26 114 install_fatal_error_handler(FatalErrorHandler);
e8be2606 115 install_out_of_memory_new_handler();
0bf4aa26
XL
116}
117
5099ac24
FG
118extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
119 sys::DisableSystemDialogsOnCrash();
120}
121
1a4d82fc 122extern "C" char *LLVMRustGetLastError(void) {
32a655c1
SL
123 char *Ret = LastError;
124 LastError = nullptr;
125 return Ret;
223e47cc
LB
126}
127
ff7c6d11 128extern "C" void LLVMRustSetLastError(const char *Err) {
32a655c1
SL
129 free((void *)LastError);
130 LastError = strdup(Err);
223e47cc
LB
131}
132
ff7c6d11
XL
133extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
134 auto ctx = new LLVMContext();
135 ctx->setDiscardValueNames(shouldDiscardNames);
136 return wrap(ctx);
137}
138
32a655c1
SL
139extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
140 const char *Triple) {
141 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
223e47cc
LB
142}
143
add651ee
FG
144extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) {
145 std::string buf;
c620b35d 146 auto SS = raw_string_ostream(buf);
add651ee
FG
147 TimerGroup::printAll(SS);
148 SS.flush();
149 *Len = buf.length();
150 char *CStr = (char *)malloc(*Len);
151 memcpy(CStr, buf.c_str(), *Len);
152 return CStr;
153}
154
155extern "C" const char *LLVMRustPrintStatistics(size_t *Len) {
156 std::string buf;
c620b35d 157 auto SS = raw_string_ostream(buf);
add651ee
FG
158 llvm::PrintStatistics(SS);
159 SS.flush();
160 *Len = buf.length();
161 char *CStr = (char *)malloc(*Len);
162 memcpy(CStr, buf.c_str(), *Len);
163 return CStr;
223e47cc
LB
164}
165
ba9703b0
XL
166extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
167 size_t NameLen) {
168 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
9346a6ac
AL
169}
170
fe692bf9
FG
171enum class LLVMRustTailCallKind {
172 None,
173 Tail,
174 MustTail,
175 NoTail,
176};
177
178static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) {
179 switch (Kind) {
180 case LLVMRustTailCallKind::None:
181 return CallInst::TailCallKind::TCK_None;
182 case LLVMRustTailCallKind::Tail:
183 return CallInst::TailCallKind::TCK_Tail;
184 case LLVMRustTailCallKind::MustTail:
185 return CallInst::TailCallKind::TCK_MustTail;
186 case LLVMRustTailCallKind::NoTail:
187 return CallInst::TailCallKind::TCK_NoTail;
188 default:
189 report_fatal_error("bad CallInst::TailCallKind.");
190 }
191}
192
193extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) {
194 unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK));
195}
196
5bcae85e 197extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
32a655c1 198 const char *Name,
ba9703b0 199 size_t NameLen,
32a655c1 200 LLVMTypeRef FunctionTy) {
ba9703b0
XL
201 return wrap(unwrap(M)
202 ->getOrInsertFunction(StringRef(Name, NameLen),
203 unwrap<FunctionType>(FunctionTy))
ba9703b0 204 .getCallee()
ba9703b0 205 );
223e47cc
LB
206}
207
32a655c1 208extern "C" LLVMValueRef
60c5eb7d 209LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
3c0e092e 210 Module *Mod = unwrap(M);
c620b35d 211 auto NameRef = StringRef(Name, NameLen);
3c0e092e
XL
212
213 // We don't use Module::getOrInsertGlobal because that returns a Constant*,
214 // which may either be the real GlobalVariable*, or a constant bitcast of it
215 // if our type doesn't match the original declaration. We always want the
216 // GlobalVariable* so we can access linkage, visibility, etc.
217 GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
218 if (!GV)
219 GV = new GlobalVariable(*Mod, unwrap(Ty), false,
220 GlobalValue::ExternalLinkage, nullptr, NameRef);
221 return wrap(GV);
9346a6ac
AL
222}
223
b7449926
XL
224extern "C" LLVMValueRef
225LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
226 return wrap(new GlobalVariable(*unwrap(M),
227 unwrap(Ty),
228 false,
229 GlobalValue::PrivateLinkage,
230 nullptr));
231}
232
32a655c1
SL
233static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
234 switch (Kind) {
235 case AlwaysInline:
236 return Attribute::AlwaysInline;
237 case ByVal:
238 return Attribute::ByVal;
239 case Cold:
240 return Attribute::Cold;
241 case InlineHint:
242 return Attribute::InlineHint;
243 case MinSize:
244 return Attribute::MinSize;
245 case Naked:
246 return Attribute::Naked;
247 case NoAlias:
248 return Attribute::NoAlias;
249 case NoCapture:
250 return Attribute::NoCapture;
064997fb
FG
251 case NoCfCheck:
252 return Attribute::NoCfCheck;
32a655c1
SL
253 case NoInline:
254 return Attribute::NoInline;
255 case NonNull:
256 return Attribute::NonNull;
257 case NoRedZone:
258 return Attribute::NoRedZone;
259 case NoReturn:
260 return Attribute::NoReturn;
261 case NoUnwind:
262 return Attribute::NoUnwind;
263 case OptimizeForSize:
264 return Attribute::OptimizeForSize;
265 case ReadOnly:
266 return Attribute::ReadOnly;
267 case SExt:
268 return Attribute::SExt;
269 case StructRet:
270 return Attribute::StructRet;
271 case UWTable:
272 return Attribute::UWTable;
273 case ZExt:
274 return Attribute::ZExt;
275 case InReg:
276 return Attribute::InReg;
8bb4bdeb
XL
277 case SanitizeThread:
278 return Attribute::SanitizeThread;
279 case SanitizeAddress:
280 return Attribute::SanitizeAddress;
281 case SanitizeMemory:
282 return Attribute::SanitizeMemory;
0bf4aa26
XL
283 case NonLazyBind:
284 return Attribute::NonLazyBind;
9fa01778
XL
285 case OptimizeNone:
286 return Attribute::OptimizeNone;
f9f354fc
XL
287 case ReadNone:
288 return Attribute::ReadNone;
6a06907d
XL
289 case SanitizeHWAddress:
290 return Attribute::SanitizeHWAddress;
291 case WillReturn:
292 return Attribute::WillReturn;
3c0e092e
XL
293 case StackProtectReq:
294 return Attribute::StackProtectReq;
295 case StackProtectStrong:
296 return Attribute::StackProtectStrong;
297 case StackProtect:
298 return Attribute::StackProtect;
5099ac24
FG
299 case NoUndef:
300 return Attribute::NoUndef;
301 case SanitizeMemTag:
302 return Attribute::SanitizeMemTag;
064997fb
FG
303 case ShadowCallStack:
304 return Attribute::ShadowCallStack;
305 case AllocSize:
306 return Attribute::AllocSize;
064997fb
FG
307 case AllocatedPointer:
308 return Attribute::AllocatedPointer;
309 case AllocAlign:
310 return Attribute::AllocAlign;
fe692bf9
FG
311 case SanitizeSafeStack:
312 return Attribute::SafeStack;
4b012472
FG
313 case FnRetThunkExtern:
314 return Attribute::FnRetThunkExtern;
e8be2606
FG
315#if LLVM_VERSION_GE(18, 0)
316 case Writable:
317 return Attribute::Writable;
318 case DeadOnUnwind:
319 return Attribute::DeadOnUnwind;
320#else
321 case Writable:
322 case DeadOnUnwind:
323 report_fatal_error("Not supported on this LLVM version");
324#endif
476ff2be 325 }
ff7c6d11 326 report_fatal_error("bad AttributeKind");
476ff2be
SL
327}
328
5e7ed085
FG
329template<typename T> static inline void AddAttributes(T *t, unsigned Index,
330 LLVMAttributeRef *Attrs, size_t AttrsLen) {
331 AttributeList PAL = t->getAttributes();
c620b35d 332 auto B = AttrBuilder(t->getContext());
9c376795 333 for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen))
5e7ed085 334 B.addAttribute(unwrap(Attr));
9ffffee4 335 AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
5e7ed085 336 t->setAttributes(PALNew);
c295e0f8
XL
337}
338
5e7ed085
FG
339extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
340 LLVMAttributeRef *Attrs, size_t AttrsLen) {
341 Function *F = unwrap<Function>(Fn);
342 AddAttributes(F, Index, Attrs, AttrsLen);
ff7c6d11
XL
343}
344
5e7ed085
FG
345extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
346 LLVMAttributeRef *Attrs, size_t AttrsLen) {
f035d41b 347 CallBase *Call = unwrap<CallBase>(Instr);
5e7ed085 348 AddAttributes(Call, Index, Attrs, AttrsLen);
416331ca
XL
349}
350
5e7ed085
FG
351extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
352 LLVMRustAttribute RustAttr) {
353 return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
6a06907d
XL
354}
355
5e7ed085
FG
356extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
357 uint64_t Bytes) {
358 return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
1a4d82fc
JJ
359}
360
5e7ed085
FG
361extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
362 uint64_t Bytes) {
363 return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
ff7c6d11
XL
364}
365
5e7ed085
FG
366extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
367 uint64_t Bytes) {
368 return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
1a4d82fc 369}
1a4d82fc 370
5e7ed085
FG
371extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
372 return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
ff7c6d11
XL
373}
374
5e7ed085
FG
375extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
376 return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
416331ca
XL
377}
378
064997fb 379extern "C" LLVMAttributeRef LLVMRustCreateElementTypeAttr(LLVMContextRef C, LLVMTypeRef Ty) {
064997fb 380 return wrap(Attribute::get(*unwrap(C), Attribute::ElementType, unwrap(Ty)));
064997fb
FG
381}
382
5e7ed085 383extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
5e7ed085
FG
384 return wrap(Attribute::getWithUWTableKind(
385 *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
1a4d82fc
JJ
386}
387
064997fb 388extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
4b012472 389 return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, std::nullopt));
064997fb
FG
390}
391
064997fb
FG
392// These values **must** match ffi::AllocKindFlags.
393// It _happens_ to match the LLVM values of llvm::AllocFnKind,
394// but that's happenstance and we do explicit conversions before
395// passing them to LLVM.
396enum class LLVMRustAllocKindFlags : uint64_t {
397 Unknown = 0,
398 Alloc = 1,
399 Realloc = 1 << 1,
400 Free = 1 << 2,
401 Uninitialized = 1 << 3,
402 Zeroed = 1 << 4,
403 Aligned = 1 << 5,
404};
405
406static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, LLVMRustAllocKindFlags B) {
407 return static_cast<LLVMRustAllocKindFlags>(static_cast<uint64_t>(A) &
408 static_cast<uint64_t>(B));
409}
410
411static bool isSet(LLVMRustAllocKindFlags F) { return F != LLVMRustAllocKindFlags::Unknown; }
412
413static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) {
414 llvm::AllocFnKind AFK = llvm::AllocFnKind::Unknown;
415 if (isSet(F & LLVMRustAllocKindFlags::Alloc)) {
416 AFK |= llvm::AllocFnKind::Alloc;
417 }
418 if (isSet(F & LLVMRustAllocKindFlags::Realloc)) {
419 AFK |= llvm::AllocFnKind::Realloc;
420 }
421 if (isSet(F & LLVMRustAllocKindFlags::Free)) {
422 AFK |= llvm::AllocFnKind::Free;
423 }
424 if (isSet(F & LLVMRustAllocKindFlags::Uninitialized)) {
425 AFK |= llvm::AllocFnKind::Uninitialized;
426 }
427 if (isSet(F & LLVMRustAllocKindFlags::Zeroed)) {
428 AFK |= llvm::AllocFnKind::Zeroed;
429 }
430 if (isSet(F & LLVMRustAllocKindFlags::Aligned)) {
431 AFK |= llvm::AllocFnKind::Aligned;
432 }
433 return AFK;
434}
064997fb
FG
435
436extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64_t AllocKindArg) {
064997fb
FG
437 return wrap(Attribute::get(*unwrap(C), Attribute::AllocKind,
438 static_cast<uint64_t>(allocKindFromRust(static_cast<LLVMRustAllocKindFlags>(AllocKindArg)))));
064997fb
FG
439}
440
487cf647
FG
441// Simplified representation of `MemoryEffects` across the FFI boundary.
442//
443// Each variant corresponds to one of the static factory methods on `MemoryEffects`.
444enum class LLVMRustMemoryEffects {
445 None,
446 ReadOnly,
447 InaccessibleMemOnly,
448};
449
450extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C,
451 LLVMRustMemoryEffects Effects) {
487cf647
FG
452 switch (Effects) {
453 case LLVMRustMemoryEffects::None:
454 return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none()));
455 case LLVMRustMemoryEffects::ReadOnly:
456 return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly()));
457 case LLVMRustMemoryEffects::InaccessibleMemOnly:
458 return wrap(Attribute::getWithMemoryEffects(*unwrap(C),
459 MemoryEffects::inaccessibleMemOnly()));
460 default:
461 report_fatal_error("bad MemoryEffects.");
462 }
487cf647
FG
463}
464
c620b35d
FG
465// Enable all fast-math flags, including those which will cause floating-point operations
466// to return poison for some well-defined inputs. This function can only be used to build
467// unsafe Rust intrinsics. That unsafety does permit additional optimizations, but at the
468// time of writing, their value is not well-understood relative to those enabled by
469// LLVMRustSetAlgebraicMath.
cdc7bbd5
XL
470//
471// https://llvm.org/docs/LangRef.html#fast-math-flags
472extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
32a655c1 473 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
2c00a5a8 474 I->setFast(true);
32a655c1 475 }
54a0048b
SL
476}
477
c620b35d
FG
478// Enable fast-math flags which permit algebraic transformations that are not allowed by
479// IEEE floating point. For example:
480// a + (b + c) = (a + b) + c
481// and
482// a / b = a * (1 / b)
483// Note that this does NOT enable any flags which can cause a floating-point operation on
484// well-defined inputs to return poison, and therefore this function can be used to build
485// safe Rust intrinsics (such as fadd_algebraic).
486//
487// https://llvm.org/docs/LangRef.html#fast-math-flags
488extern "C" void LLVMRustSetAlgebraicMath(LLVMValueRef V) {
489 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
490 I->setHasAllowReassoc(true);
491 I->setHasAllowContract(true);
492 I->setHasAllowReciprocal(true);
493 I->setHasNoSignedZeros(true);
494 }
495}
496
497// Enable the reassoc fast-math flag, allowing transformations that pretend
498// floating-point addition and multiplication are associative.
499//
500// Note that this does NOT enable any flags which can cause a floating-point operation on
501// well-defined inputs to return poison, and therefore this function can be used to build
502// safe Rust intrinsics (such as fadd_algebraic).
503//
504// https://llvm.org/docs/LangRef.html#fast-math-flags
505extern "C" void LLVMRustSetAllowReassoc(LLVMValueRef V) {
506 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
507 I->setHasAllowReassoc(true);
508 }
509}
510
32a655c1 511extern "C" LLVMValueRef
136023e0
XL
512LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
513 const char *Name, LLVMAtomicOrdering Order) {
f035d41b 514 Value *Ptr = unwrap(Source);
136023e0 515 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
32a655c1 516 LI->setAtomic(fromRust(Order));
f035d41b 517 return wrap(LI);
970d7e83
LB
518}
519
5bcae85e 520extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
32a655c1
SL
521 LLVMValueRef V,
522 LLVMValueRef Target,
ff7c6d11 523 LLVMAtomicOrdering Order) {
f035d41b 524 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
32a655c1 525 SI->setAtomic(fromRust(Order));
f035d41b 526 return wrap(SI);
32a655c1
SL
527}
528
5bcae85e 529enum class LLVMRustAsmDialect {
32a655c1
SL
530 Att,
531 Intel,
5bcae85e
SL
532};
533
32a655c1
SL
534static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
535 switch (Dialect) {
536 case LLVMRustAsmDialect::Att:
537 return InlineAsm::AD_ATT;
538 case LLVMRustAsmDialect::Intel:
539 return InlineAsm::AD_Intel;
540 default:
ff7c6d11 541 report_fatal_error("bad AsmDialect.");
32a655c1 542 }
5bcae85e
SL
543}
544
ba9703b0
XL
545extern "C" LLVMValueRef
546LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
547 char *Constraints, size_t ConstraintsLen,
548 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
a2a8927a 549 LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
a2a8927a
XL
550 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
551 StringRef(AsmString, AsmStringLen),
552 StringRef(Constraints, ConstraintsLen),
553 HasSideEffects, IsAlignStack,
554 fromRust(Dialect), CanThrow));
223e47cc 555}
970d7e83 556
ba9703b0
XL
557extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
558 size_t ConstraintsLen) {
064997fb
FG
559 // llvm::Error converts to true if it is an error.
560 return !llvm::errorToBool(InlineAsm::verify(
561 unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
0bf4aa26
XL
562}
563
32a655c1 564typedef DIBuilder *LLVMRustDIBuilderRef;
970d7e83 565
3b2f2976 566template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
32a655c1 567 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
62682a34
SL
568}
569
62682a34
SL
570#define DIDescriptor DIScope
571#define DIArray DINodeArray
32a655c1 572#define unwrapDI unwrapDIPtr
62682a34 573
476ff2be
SL
574// These values **must** match debuginfo::DIFlags! They also *happen*
575// to match LLVM, but that isn't required as we do giant sets of
576// matching below. The value shouldn't be directly passed to LLVM.
577enum class LLVMRustDIFlags : uint32_t {
32a655c1
SL
578 FlagZero = 0,
579 FlagPrivate = 1,
580 FlagProtected = 2,
581 FlagPublic = 3,
582 FlagFwdDecl = (1 << 2),
583 FlagAppleBlock = (1 << 3),
584 FlagBlockByrefStruct = (1 << 4),
585 FlagVirtual = (1 << 5),
586 FlagArtificial = (1 << 6),
587 FlagExplicit = (1 << 7),
588 FlagPrototyped = (1 << 8),
589 FlagObjcClassComplete = (1 << 9),
590 FlagObjectPointer = (1 << 10),
591 FlagVector = (1 << 11),
592 FlagStaticMember = (1 << 12),
593 FlagLValueReference = (1 << 13),
594 FlagRValueReference = (1 << 14),
2c00a5a8
XL
595 FlagExternalTypeRef = (1 << 15),
596 FlagIntroducedVirtual = (1 << 18),
597 FlagBitField = (1 << 19),
598 FlagNoReturn = (1 << 20),
32a655c1 599 // Do not add values that are not supported by the minimum LLVM
2c00a5a8 600 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
476ff2be
SL
601};
602
32a655c1
SL
603inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
604 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
605 static_cast<uint32_t>(B));
476ff2be
SL
606}
607
32a655c1
SL
608inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
609 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
610 static_cast<uint32_t>(B));
476ff2be
SL
611}
612
32a655c1
SL
613inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
614 return A = A | B;
476ff2be
SL
615}
616
32a655c1 617inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
476ff2be 618
32a655c1
SL
619inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
620 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
476ff2be
SL
621}
622
32a655c1
SL
623static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
624 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
476ff2be 625
32a655c1
SL
626 switch (visibility(Flags)) {
627 case LLVMRustDIFlags::FlagPrivate:
628 Result |= DINode::DIFlags::FlagPrivate;
629 break;
630 case LLVMRustDIFlags::FlagProtected:
631 Result |= DINode::DIFlags::FlagProtected;
632 break;
633 case LLVMRustDIFlags::FlagPublic:
634 Result |= DINode::DIFlags::FlagPublic;
635 break;
636 default:
637 // The rest are handled below
638 break;
639 }
476ff2be 640
32a655c1
SL
641 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
642 Result |= DINode::DIFlags::FlagFwdDecl;
643 }
644 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
645 Result |= DINode::DIFlags::FlagAppleBlock;
646 }
32a655c1
SL
647 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
648 Result |= DINode::DIFlags::FlagVirtual;
649 }
650 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
651 Result |= DINode::DIFlags::FlagArtificial;
652 }
653 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
654 Result |= DINode::DIFlags::FlagExplicit;
655 }
656 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
657 Result |= DINode::DIFlags::FlagPrototyped;
658 }
659 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
660 Result |= DINode::DIFlags::FlagObjcClassComplete;
661 }
662 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
663 Result |= DINode::DIFlags::FlagObjectPointer;
664 }
665 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
666 Result |= DINode::DIFlags::FlagVector;
667 }
668 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
669 Result |= DINode::DIFlags::FlagStaticMember;
670 }
671 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
672 Result |= DINode::DIFlags::FlagLValueReference;
673 }
674 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
675 Result |= DINode::DIFlags::FlagRValueReference;
676 }
2c00a5a8
XL
677 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
678 Result |= DINode::DIFlags::FlagIntroducedVirtual;
679 }
680 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
681 Result |= DINode::DIFlags::FlagBitField;
682 }
2c00a5a8
XL
683 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
684 Result |= DINode::DIFlags::FlagNoReturn;
685 }
476ff2be 686
32a655c1 687 return Result;
476ff2be
SL
688}
689
9fa01778
XL
690// These values **must** match debuginfo::DISPFlags! They also *happen*
691// to match LLVM, but that isn't required as we do giant sets of
692// matching below. The value shouldn't be directly passed to LLVM.
693enum class LLVMRustDISPFlags : uint32_t {
694 SPFlagZero = 0,
695 SPFlagVirtual = 1,
696 SPFlagPureVirtual = 2,
697 SPFlagLocalToUnit = (1 << 2),
698 SPFlagDefinition = (1 << 3),
699 SPFlagOptimized = (1 << 4),
532ac7d7 700 SPFlagMainSubprogram = (1 << 5),
9fa01778
XL
701 // Do not add values that are not supported by the minimum LLVM
702 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
703 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
704};
705
706inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
707 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
708 static_cast<uint32_t>(B));
709}
710
711inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
712 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
713 static_cast<uint32_t>(B));
714}
715
716inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
717 return A = A | B;
718}
719
720inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
721
722inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
723 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
724}
725
9fa01778
XL
726static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
727 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
728
729 switch (virtuality(SPFlags)) {
730 case LLVMRustDISPFlags::SPFlagVirtual:
731 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
732 break;
733 case LLVMRustDISPFlags::SPFlagPureVirtual:
734 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
735 break;
736 default:
737 // The rest are handled below
738 break;
739 }
740
741 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
742 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
743 }
744 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
745 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
746 }
747 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
748 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
749 }
532ac7d7
XL
750 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
751 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
752 }
9fa01778
XL
753
754 return Result;
755}
9fa01778
XL
756
757enum class LLVMRustDebugEmissionKind {
758 NoDebug,
759 FullDebug,
760 LineTablesOnly,
353b0b11 761 DebugDirectivesOnly,
9fa01778
XL
762};
763
764static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
765 switch (Kind) {
766 case LLVMRustDebugEmissionKind::NoDebug:
767 return DICompileUnit::DebugEmissionKind::NoDebug;
768 case LLVMRustDebugEmissionKind::FullDebug:
769 return DICompileUnit::DebugEmissionKind::FullDebug;
770 case LLVMRustDebugEmissionKind::LineTablesOnly:
771 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
353b0b11
FG
772 case LLVMRustDebugEmissionKind::DebugDirectivesOnly:
773 return DICompileUnit::DebugEmissionKind::DebugDirectivesOnly;
9fa01778
XL
774 default:
775 report_fatal_error("bad DebugEmissionKind.");
776 }
777}
778
4b012472
FG
779enum class LLVMRustDebugNameTableKind {
780 Default,
781 GNU,
782 None,
783};
784
785static DICompileUnit::DebugNameTableKind fromRust(LLVMRustDebugNameTableKind Kind) {
786 switch (Kind) {
787 case LLVMRustDebugNameTableKind::Default:
788 return DICompileUnit::DebugNameTableKind::Default;
789 case LLVMRustDebugNameTableKind::GNU:
790 return DICompileUnit::DebugNameTableKind::GNU;
791 case LLVMRustDebugNameTableKind::None:
792 return DICompileUnit::DebugNameTableKind::None;
793 default:
794 report_fatal_error("bad DebugNameTableKind.");
795 }
796}
797
ba9703b0
XL
798enum class LLVMRustChecksumKind {
799 None,
800 MD5,
801 SHA1,
29967ef6 802 SHA256,
ba9703b0
XL
803};
804
487cf647 805static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
ba9703b0
XL
806 switch (Kind) {
807 case LLVMRustChecksumKind::None:
9c376795 808 return std::nullopt;
ba9703b0
XL
809 case LLVMRustChecksumKind::MD5:
810 return DIFile::ChecksumKind::CSK_MD5;
811 case LLVMRustChecksumKind::SHA1:
812 return DIFile::ChecksumKind::CSK_SHA1;
29967ef6
XL
813 case LLVMRustChecksumKind::SHA256:
814 return DIFile::ChecksumKind::CSK_SHA256;
ba9703b0
XL
815 default:
816 report_fatal_error("bad ChecksumKind.");
817 }
818}
819
62682a34 820extern "C" uint32_t LLVMRustDebugMetadataVersion() {
32a655c1 821 return DEBUG_METADATA_VERSION;
62682a34
SL
822}
823
5869c6ff
XL
824extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
825
32a655c1 826extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
62682a34 827
32a655c1 828extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
1a4d82fc 829
e8be2606 830extern "C" void LLVMRustAddModuleFlagU32(
5099ac24
FG
831 LLVMModuleRef M,
832 Module::ModFlagBehavior MergeBehavior,
833 const char *Name,
834 uint32_t Value) {
835 unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
970d7e83
LB
836}
837
e8be2606
FG
838extern "C" void LLVMRustAddModuleFlagString(
839 LLVMModuleRef M,
840 Module::ModFlagBehavior MergeBehavior,
841 const char *Name,
842 const char *Value,
843 size_t ValueLen) {
844 unwrap(M)->addModuleFlag(MergeBehavior, Name,
845 MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
846}
847
923072b8
FG
848extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
849 size_t Len) {
850 return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
851}
852
923072b8
FG
853extern "C" void LLVMRustGlobalAddMetadata(
854 LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
855 unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
856}
857
5bcae85e 858extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
32a655c1 859 return new DIBuilder(*unwrap(M));
970d7e83
LB
860}
861
5bcae85e 862extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
32a655c1 863 delete Builder;
970d7e83
LB
864}
865
5bcae85e 866extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
32a655c1 867 Builder->finalize();
970d7e83
LB
868}
869
3b2f2976
XL
870extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
871 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
74b04a01
XL
872 const char *Producer, size_t ProducerLen, bool isOptimized,
873 const char *Flags, unsigned RuntimeVer,
874 const char *SplitName, size_t SplitNameLen,
fc512014 875 LLVMRustDebugEmissionKind Kind,
4b012472
FG
876 uint64_t DWOId, bool SplitDebugInlining,
877 LLVMRustDebugNameTableKind TableKind) {
8bb4bdeb
XL
878 auto *File = unwrapDI<DIFile>(FileRef);
879
74b04a01
XL
880 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
881 isOptimized, Flags, RuntimeVer,
882 StringRef(SplitName, SplitNameLen),
4b012472
FG
883 fromRust(Kind), DWOId, SplitDebugInlining,
884 false, fromRust(TableKind)));
32a655c1
SL
885}
886
74b04a01
XL
887extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
888 LLVMRustDIBuilderRef Builder,
889 const char *Filename, size_t FilenameLen,
ba9703b0
XL
890 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
891 const char *Checksum, size_t ChecksumLen) {
487cf647 892
487cf647 893 std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
487cf647 894 std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
ba9703b0
XL
895 if (llvmCSKind)
896 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
74b04a01 897 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
ba9703b0
XL
898 StringRef(Directory, DirectoryLen),
899 CSInfo));
32a655c1
SL
900}
901
3b2f2976 902extern "C" LLVMMetadataRef
32a655c1 903LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
3b2f2976 904 LLVMMetadataRef ParameterTypes) {
32a655c1 905 return wrap(Builder->createSubroutineType(
32a655c1 906 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
970d7e83
LB
907}
908
3b2f2976 909extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
74b04a01
XL
910 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
911 const char *Name, size_t NameLen,
912 const char *LinkageName, size_t LinkageNameLen,
913 LLVMMetadataRef File, unsigned LineNo,
9fa01778 914 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
29967ef6 915 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
9fa01778 916 LLVMMetadataRef Decl) {
32a655c1
SL
917 DITemplateParameterArray TParams =
918 DITemplateParameterArray(unwrap<MDTuple>(TParam));
532ac7d7
XL
919 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
920 DINode::DIFlags llvmFlags = fromRust(Flags);
9fa01778 921 DISubprogram *Sub = Builder->createFunction(
74b04a01
XL
922 unwrapDI<DIScope>(Scope),
923 StringRef(Name, NameLen),
924 StringRef(LinkageName, LinkageNameLen),
925 unwrapDI<DIFile>(File), LineNo,
926 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
532ac7d7 927 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
29967ef6
XL
928 if (MaybeFn)
929 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
32a655c1 930 return wrap(Sub);
970d7e83
LB
931}
932
353b0b11
FG
933extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
934 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
935 const char *Name, size_t NameLen,
936 const char *LinkageName, size_t LinkageNameLen,
937 LLVMMetadataRef File, unsigned LineNo,
938 LLVMMetadataRef Ty, LLVMRustDIFlags Flags,
939 LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
940 DITemplateParameterArray TParams =
941 DITemplateParameterArray(unwrap<MDTuple>(TParam));
942 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
943 DINode::DIFlags llvmFlags = fromRust(Flags);
944 DISubprogram *Sub = Builder->createMethod(
945 unwrapDI<DIScope>(Scope),
946 StringRef(Name, NameLen),
947 StringRef(LinkageName, LinkageNameLen),
948 unwrapDI<DIFile>(File), LineNo,
949 unwrapDI<DISubroutineType>(Ty),
950 0, 0, nullptr, // VTable params aren't used
951 llvmFlags, llvmSPFlags, TParams);
952 return wrap(Sub);
953}
954
74b04a01
XL
955extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
956 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
f9f354fc 957 uint64_t SizeInBits, unsigned Encoding) {
74b04a01 958 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
970d7e83 959}
1a4d82fc 960
f035d41b
XL
961extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
962 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
963 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
964 return wrap(Builder->createTypedef(
965 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
29967ef6 966 LineNo, unwrapDIPtr<DIScope>(Scope)));
f035d41b
XL
967}
968
3b2f2976
XL
969extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
970 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
74b04a01
XL
971 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
972 const char *Name, size_t NameLen) {
32a655c1 973 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
3b2f2976 974 SizeInBits, AlignInBits,
74b04a01
XL
975 AddressSpace,
976 StringRef(Name, NameLen)));
970d7e83
LB
977}
978
3b2f2976 979extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
74b04a01
XL
980 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
981 const char *Name, size_t NameLen,
3b2f2976 982 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
8bb4bdeb 983 uint32_t AlignInBits, LLVMRustDIFlags Flags,
3b2f2976
XL
984 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
985 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
74b04a01 986 const char *UniqueId, size_t UniqueIdLen) {
32a655c1 987 return wrap(Builder->createStructType(
74b04a01
XL
988 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
989 unwrapDI<DIFile>(File), LineNumber,
32a655c1
SL
990 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
991 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
74b04a01 992 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
970d7e83
LB
993}
994
a1dfa0c6 995extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
74b04a01
XL
996 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
997 const char *Name, size_t NameLen,
a1dfa0c6
XL
998 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
999 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
74b04a01 1000 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
a1dfa0c6 1001 return wrap(Builder->createVariantPart(
74b04a01
XL
1002 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1003 unwrapDI<DIFile>(File), LineNumber,
a1dfa0c6 1004 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
74b04a01 1005 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
a1dfa0c6
XL
1006}
1007
3b2f2976 1008extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
74b04a01
XL
1009 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1010 const char *Name, size_t NameLen,
3b2f2976 1011 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
8bb4bdeb 1012 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
3b2f2976 1013 LLVMMetadataRef Ty) {
74b04a01
XL
1014 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
1015 StringRef(Name, NameLen),
32a655c1
SL
1016 unwrapDI<DIFile>(File), LineNo,
1017 SizeInBits, AlignInBits, OffsetInBits,
1018 fromRust(Flags), unwrapDI<DIType>(Ty)));
970d7e83 1019}
1a4d82fc 1020
a1dfa0c6
XL
1021extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
1022 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
74b04a01
XL
1023 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
1024 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
a1dfa0c6 1025 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
a1dfa0c6
XL
1026 llvm::ConstantInt* D = nullptr;
1027 if (Discriminant) {
1028 D = unwrap<llvm::ConstantInt>(Discriminant);
1029 }
74b04a01
XL
1030 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
1031 StringRef(Name, NameLen),
a1dfa0c6
XL
1032 unwrapDI<DIFile>(File), LineNo,
1033 SizeInBits, AlignInBits, OffsetInBits, D,
1034 fromRust(Flags), unwrapDI<DIType>(Ty)));
a1dfa0c6
XL
1035}
1036
f2b60f7d
FG
1037extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType(
1038 LLVMRustDIBuilderRef Builder,
1039 LLVMMetadataRef Scope,
1040 const char *Name,
1041 size_t NameLen,
1042 LLVMMetadataRef File,
1043 unsigned LineNo,
1044 LLVMMetadataRef Ty,
1045 LLVMRustDIFlags Flags,
1046 LLVMValueRef val,
1047 uint32_t AlignInBits
1048) {
1049 return wrap(Builder->createStaticMemberType(
1050 unwrapDI<DIDescriptor>(Scope),
1051 StringRef(Name, NameLen),
1052 unwrapDI<DIFile>(File),
1053 LineNo,
1054 unwrapDI<DIType>(Ty),
1055 fromRust(Flags),
1056 unwrap<llvm::ConstantInt>(val),
4b012472
FG
1057#if LLVM_VERSION_GE(18, 0)
1058 llvm::dwarf::DW_TAG_member,
1059#endif
f2b60f7d
FG
1060 AlignInBits
1061 ));
1062}
1063
3b2f2976
XL
1064extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
1065 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1066 LLVMMetadataRef File, unsigned Line, unsigned Col) {
32a655c1
SL
1067 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
1068 unwrapDI<DIFile>(File), Line, Col));
1a4d82fc
JJ
1069}
1070
3b2f2976 1071extern "C" LLVMMetadataRef
32a655c1 1072LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
3b2f2976
XL
1073 LLVMMetadataRef Scope,
1074 LLVMMetadataRef File) {
32a655c1
SL
1075 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
1076 unwrapDI<DIFile>(File)));
9e0c209e
SL
1077}
1078
3b2f2976 1079extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
74b04a01
XL
1080 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
1081 const char *Name, size_t NameLen,
1082 const char *LinkageName, size_t LinkageNameLen,
1083 LLVMMetadataRef File, unsigned LineNo,
3b2f2976
XL
1084 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
1085 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
cc61c64b 1086 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
476ff2be 1087
32a655c1
SL
1088 llvm::DIExpression *InitExpr = nullptr;
1089 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
1090 InitExpr = Builder->createConstantValueExpression(
1091 IntVal->getValue().getSExtValue());
1092 } else if (llvm::ConstantFP *FPVal =
1093 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
1094 InitExpr = Builder->createConstantValueExpression(
1095 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
1096 }
476ff2be 1097
cc61c64b 1098 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
74b04a01
XL
1099 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
1100 StringRef(LinkageName, LinkageNameLen),
cc61c64b 1101 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
dfeec247 1102 /* isDefined */ true,
a1dfa0c6 1103 InitExpr, unwrapDIPtr<MDNode>(Decl),
a1dfa0c6 1104 /* templateParams */ nullptr,
a1dfa0c6 1105 AlignInBits);
cc61c64b
XL
1106
1107 InitVal->setMetadata("dbg", VarExpr);
1108
1109 return wrap(VarExpr);
970d7e83 1110}
1a4d82fc 1111
3b2f2976
XL
1112extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
1113 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
74b04a01
XL
1114 const char *Name, size_t NameLen,
1115 LLVMMetadataRef File, unsigned LineNo,
3b2f2976 1116 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
8bb4bdeb 1117 unsigned ArgNo, uint32_t AlignInBits) {
32a655c1
SL
1118 if (Tag == 0x100) { // DW_TAG_auto_variable
1119 return wrap(Builder->createAutoVariable(
74b04a01
XL
1120 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1121 unwrapDI<DIFile>(File), LineNo,
8faf50e0 1122 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
32a655c1
SL
1123 } else {
1124 return wrap(Builder->createParameterVariable(
74b04a01
XL
1125 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
1126 unwrapDI<DIFile>(File), LineNo,
1127 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
32a655c1 1128 }
970d7e83
LB
1129}
1130
3b2f2976 1131extern "C" LLVMMetadataRef
32a655c1 1132LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
3b2f2976
XL
1133 uint32_t AlignInBits, LLVMMetadataRef Ty,
1134 LLVMMetadataRef Subscripts) {
32a655c1
SL
1135 return wrap(
1136 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
1137 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
970d7e83
LB
1138}
1139
3b2f2976 1140extern "C" LLVMMetadataRef
32a655c1
SL
1141LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
1142 int64_t Count) {
1143 return wrap(Builder->getOrCreateSubrange(Lo, Count));
970d7e83
LB
1144}
1145
3b2f2976 1146extern "C" LLVMMetadataRef
32a655c1 1147LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
3b2f2976 1148 LLVMMetadataRef *Ptr, unsigned Count) {
32a655c1
SL
1149 Metadata **DataValue = unwrap(Ptr);
1150 return wrap(
1151 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
970d7e83
LB
1152}
1153
5bcae85e 1154extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
3b2f2976 1155 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
a2a8927a 1156 uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
970d7e83 1157 LLVMBasicBlockRef InsertAtEnd) {
c620b35d 1158 auto Result = Builder->insertDeclare(
32a655c1 1159 unwrap(V), unwrap<DILocalVariable>(VarInfo),
a2a8927a 1160 Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
29967ef6 1161 DebugLoc(cast<MDNode>(unwrap(DL))),
c620b35d
FG
1162 unwrap(InsertAtEnd));
1163#if LLVM_VERSION_GE(19, 0)
1164 return wrap(Result.get<llvm::Instruction *>());
1165#else
1166 return wrap(Result);
1167#endif
32a655c1
SL
1168}
1169
74b04a01
XL
1170extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
1171 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
487cf647
FG
1172 const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
1173 return wrap(Builder->createEnumerator(StringRef(Name, NameLen),
9c376795 1174 APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned)));
1a4d82fc
JJ
1175}
1176
3b2f2976 1177extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
74b04a01
XL
1178 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1179 const char *Name, size_t NameLen,
3b2f2976
XL
1180 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1181 uint32_t AlignInBits, LLVMMetadataRef Elements,
9fa01778 1182 LLVMMetadataRef ClassTy, bool IsScoped) {
a1dfa0c6 1183 return wrap(Builder->createEnumerationType(
74b04a01
XL
1184 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
1185 unwrapDI<DIFile>(File), LineNumber,
a1dfa0c6 1186 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
4b012472
FG
1187 unwrapDI<DIType>(ClassTy),
1188#if LLVM_VERSION_GE(18, 0)
1189 /* RunTimeLang */ 0,
1190#endif
1191 "", IsScoped));
1a4d82fc
JJ
1192}
1193
3b2f2976 1194extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
74b04a01
XL
1195 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1196 const char *Name, size_t NameLen,
3b2f2976
XL
1197 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
1198 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
74b04a01 1199 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
32a655c1 1200 return wrap(Builder->createUnionType(
74b04a01
XL
1201 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
1202 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
1203 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
1204 StringRef(UniqueId, UniqueIdLen)));
1a4d82fc
JJ
1205}
1206
3b2f2976 1207extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
74b04a01 1208 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
f9f354fc 1209 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
f035d41b
XL
1210 bool IsDefault = false; // FIXME: should we ever set this true?
1211 return wrap(Builder->createTemplateTypeParameter(
1212 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
32a655c1
SL
1213}
1214
74b04a01
XL
1215extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1216 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1217 const char *Name, size_t NameLen, bool ExportSymbols) {
32a655c1 1218 return wrap(Builder->createNameSpace(
74b04a01
XL
1219 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1220 ));
1a4d82fc
JJ
1221}
1222
32a655c1 1223extern "C" void
a1dfa0c6
XL
1224LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1225 LLVMMetadataRef CompositeTy,
1226 LLVMMetadataRef Elements,
1227 LLVMMetadataRef Params) {
32a655c1 1228 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
a1dfa0c6
XL
1229 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1230 DINodeArray(unwrap<MDTuple>(Params)));
1a4d82fc
JJ
1231}
1232
29967ef6 1233extern "C" LLVMMetadataRef
5869c6ff 1234LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
6a06907d 1235 LLVMMetadataRef ScopeRef,
3b2f2976 1236 LLVMMetadataRef InlinedAt) {
6a06907d
XL
1237 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1238 DILocation *Loc = DILocation::get(
1239 Scope->getContext(), Line, Column, Scope,
1240 unwrapDIPtr<MDNode>(InlinedAt));
1241 return wrap(Loc);
85aaf69f
SL
1242}
1243
a2a8927a 1244extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
32a655c1 1245 return dwarf::DW_OP_deref;
5bcae85e
SL
1246}
1247
a2a8927a 1248extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
2c00a5a8 1249 return dwarf::DW_OP_plus_uconst;
2c00a5a8 1250}
5bcae85e 1251
487cf647
FG
1252extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
1253 return dwarf::DW_OP_LLVM_fragment;
1254}
1255
32a655c1 1256extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
c620b35d 1257 auto OS = RawRustStringOstream(Str);
32a655c1 1258 unwrap<llvm::Type>(Ty)->print(OS);
1a4d82fc
JJ
1259}
1260
32a655c1
SL
1261extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1262 RustStringRef Str) {
c620b35d 1263 auto OS = RawRustStringOstream(Str);
7cac9316
XL
1264 if (!V) {
1265 OS << "(null)";
1266 } else {
1267 OS << "(";
1268 unwrap<llvm::Value>(V)->getType()->print(OS);
1269 OS << ":";
1270 unwrap<llvm::Value>(V)->print(OS);
1271 OS << ")";
1272 }
1a4d82fc
JJ
1273}
1274
1a4d82fc 1275DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1a4d82fc 1276
32a655c1 1277extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
c620b35d 1278 auto OS = RawRustStringOstream(Str);
32a655c1 1279 unwrap(T)->print(OS);
1a4d82fc
JJ
1280}
1281
32a655c1
SL
1282extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1283 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
3b2f2976
XL
1284 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1285 RustStringRef FilenameOut, RustStringRef MessageOut) {
32a655c1
SL
1286 // Undefined to call this not on an optimization diagnostic!
1287 llvm::DiagnosticInfoOptimizationBase *Opt =
1288 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1a4d82fc 1289
c620b35d 1290 auto PassNameOS = RawRustStringOstream(PassNameOut);
32a655c1
SL
1291 PassNameOS << Opt->getPassName();
1292 *FunctionOut = wrap(&Opt->getFunction());
3b2f2976 1293
c620b35d 1294 auto FilenameOS = RawRustStringOstream(FilenameOut);
3b2f2976
XL
1295 DiagnosticLocation loc = Opt->getLocation();
1296 if (loc.isValid()) {
1297 *Line = loc.getLine();
1298 *Column = loc.getColumn();
9fa01778 1299 FilenameOS << loc.getAbsolutePath();
3b2f2976 1300 }
3b2f2976 1301
c620b35d 1302 auto MessageOS = RawRustStringOstream(MessageOut);
32a655c1 1303 MessageOS << Opt->getMsg();
1a4d82fc
JJ
1304}
1305
f035d41b
XL
1306enum class LLVMRustDiagnosticLevel {
1307 Error,
1308 Warning,
1309 Note,
1310 Remark,
1311};
1312
85aaf69f 1313extern "C" void
f035d41b
XL
1314LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1315 LLVMRustDiagnosticLevel *LevelOut,
c620b35d 1316 uint64_t *CookieOut,
94222f64 1317 LLVMTwineRef *MessageOut) {
32a655c1
SL
1318 // Undefined to call this not on an inline assembly diagnostic!
1319 llvm::DiagnosticInfoInlineAsm *IA =
1320 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
85aaf69f 1321
32a655c1
SL
1322 *CookieOut = IA->getLocCookie();
1323 *MessageOut = wrap(&IA->getMsgStr());
f035d41b
XL
1324
1325 switch (IA->getSeverity()) {
1326 case DS_Error:
1327 *LevelOut = LLVMRustDiagnosticLevel::Error;
1328 break;
1329 case DS_Warning:
1330 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1331 break;
1332 case DS_Note:
1333 *LevelOut = LLVMRustDiagnosticLevel::Note;
1334 break;
1335 case DS_Remark:
1336 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1337 break;
1338 default:
1339 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1340 }
85aaf69f
SL
1341}
1342
32a655c1
SL
1343extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1344 RustStringRef Str) {
c620b35d
FG
1345 auto OS = RawRustStringOstream(Str);
1346 auto DP = DiagnosticPrinterRawOStream(OS);
32a655c1 1347 unwrap(DI)->print(DP);
1a4d82fc
JJ
1348}
1349
5bcae85e 1350enum class LLVMRustDiagnosticKind {
32a655c1
SL
1351 Other,
1352 InlineAsm,
1353 StackSize,
1354 DebugMetadataVersion,
1355 SampleProfile,
1356 OptimizationRemark,
1357 OptimizationRemarkMissed,
1358 OptimizationRemarkAnalysis,
1359 OptimizationRemarkAnalysisFPCommute,
1360 OptimizationRemarkAnalysisAliasing,
1361 OptimizationRemarkOther,
1362 OptimizationFailure,
0531ce1d 1363 PGOProfile,
b7449926 1364 Linker,
1b1a35ee 1365 Unsupported,
94222f64 1366 SrcMgr,
5bcae85e
SL
1367};
1368
32a655c1
SL
1369static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1370 switch (Kind) {
1371 case DK_InlineAsm:
1372 return LLVMRustDiagnosticKind::InlineAsm;
1373 case DK_StackSize:
1374 return LLVMRustDiagnosticKind::StackSize;
1375 case DK_DebugMetadataVersion:
1376 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1377 case DK_SampleProfile:
1378 return LLVMRustDiagnosticKind::SampleProfile;
1379 case DK_OptimizationRemark:
a2a8927a 1380 case DK_MachineOptimizationRemark:
32a655c1
SL
1381 return LLVMRustDiagnosticKind::OptimizationRemark;
1382 case DK_OptimizationRemarkMissed:
a2a8927a 1383 case DK_MachineOptimizationRemarkMissed:
32a655c1
SL
1384 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1385 case DK_OptimizationRemarkAnalysis:
a2a8927a 1386 case DK_MachineOptimizationRemarkAnalysis:
32a655c1 1387 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
32a655c1
SL
1388 case DK_OptimizationRemarkAnalysisFPCommute:
1389 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1390 case DK_OptimizationRemarkAnalysisAliasing:
1391 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
0531ce1d
XL
1392 case DK_PGOProfile:
1393 return LLVMRustDiagnosticKind::PGOProfile;
b7449926
XL
1394 case DK_Linker:
1395 return LLVMRustDiagnosticKind::Linker;
1b1a35ee
XL
1396 case DK_Unsupported:
1397 return LLVMRustDiagnosticKind::Unsupported;
94222f64
XL
1398 case DK_SrcMgr:
1399 return LLVMRustDiagnosticKind::SrcMgr;
32a655c1 1400 default:
32a655c1
SL
1401 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1402 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1403 : LLVMRustDiagnosticKind::Other;
5bcae85e
SL
1404 }
1405}
1406
32a655c1
SL
1407extern "C" LLVMRustDiagnosticKind
1408LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1409 return toRust((DiagnosticKind)unwrap(DI)->getKind());
5bcae85e 1410}
f035d41b 1411
5bcae85e
SL
1412// This is kept distinct from LLVMGetTypeKind, because when
1413// a new type kind is added, the Rust-side enum must be
1414// updated or UB will result.
1415extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1416 switch (unwrap(Ty)->getTypeID()) {
1417 case Type::VoidTyID:
1418 return LLVMVoidTypeKind;
1419 case Type::HalfTyID:
1420 return LLVMHalfTypeKind;
1421 case Type::FloatTyID:
1422 return LLVMFloatTypeKind;
1423 case Type::DoubleTyID:
1424 return LLVMDoubleTypeKind;
1425 case Type::X86_FP80TyID:
1426 return LLVMX86_FP80TypeKind;
1427 case Type::FP128TyID:
1428 return LLVMFP128TypeKind;
1429 case Type::PPC_FP128TyID:
1430 return LLVMPPC_FP128TypeKind;
1431 case Type::LabelTyID:
1432 return LLVMLabelTypeKind;
1433 case Type::MetadataTyID:
1434 return LLVMMetadataTypeKind;
1435 case Type::IntegerTyID:
1436 return LLVMIntegerTypeKind;
1437 case Type::FunctionTyID:
1438 return LLVMFunctionTypeKind;
1439 case Type::StructTyID:
1440 return LLVMStructTypeKind;
1441 case Type::ArrayTyID:
1442 return LLVMArrayTypeKind;
1443 case Type::PointerTyID:
1444 return LLVMPointerTypeKind;
f035d41b
XL
1445 case Type::FixedVectorTyID:
1446 return LLVMVectorTypeKind;
5bcae85e
SL
1447 case Type::X86_MMXTyID:
1448 return LLVMX86_MMXTypeKind;
5bcae85e
SL
1449 case Type::TokenTyID:
1450 return LLVMTokenTypeKind;
f035d41b
XL
1451 case Type::ScalableVectorTyID:
1452 return LLVMScalableVectorTypeKind;
1453 case Type::BFloatTyID:
1454 return LLVMBFloatTypeKind;
6a06907d
XL
1455 case Type::X86_AMXTyID:
1456 return LLVMX86_AMXTypeKind;
9c376795
FG
1457 default:
1458 {
1459 std::string error;
c620b35d 1460 auto stream = llvm::raw_string_ostream(error);
9c376795
FG
1461 stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID()
1462 << " for the type: " << *unwrap(Ty);
1463 stream.flush();
1464 report_fatal_error(error.c_str());
1465 }
5bcae85e 1466 }
1a4d82fc
JJ
1467}
1468
1a4d82fc
JJ
1469DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1470
94222f64
XL
1471extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1472 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
94222f64
XL
1473 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1474 *Cookie = SM->getLocCookie();
1475 return wrap(&SM->getSMDiag());
94222f64
XL
1476}
1477
f9f354fc
XL
1478extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1479 RustStringRef MessageOut,
1480 RustStringRef BufferOut,
f035d41b 1481 LLVMRustDiagnosticLevel* LevelOut,
f9f354fc
XL
1482 unsigned* LocOut,
1483 unsigned* RangesOut,
1484 size_t* NumRanges) {
1485 SMDiagnostic& D = *unwrap(DRef);
c620b35d 1486 auto MessageOS = RawRustStringOstream(MessageOut);
f9f354fc
XL
1487 MessageOS << D.getMessage();
1488
f035d41b
XL
1489 switch (D.getKind()) {
1490 case SourceMgr::DK_Error:
1491 *LevelOut = LLVMRustDiagnosticLevel::Error;
1492 break;
1493 case SourceMgr::DK_Warning:
1494 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1495 break;
1496 case SourceMgr::DK_Note:
1497 *LevelOut = LLVMRustDiagnosticLevel::Note;
1498 break;
1499 case SourceMgr::DK_Remark:
1500 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1501 break;
1502 default:
1503 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1504 }
1505
f9f354fc
XL
1506 if (D.getLoc() == SMLoc())
1507 return false;
1508
1509 const SourceMgr &LSM = *D.getSourceMgr();
1510 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1511 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1512
1513 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1514
1515 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1516 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1517 for (size_t i = 0; i < *NumRanges; i++) {
1518 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1519 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1520 }
1521
1522 return true;
1a4d82fc 1523}
c1a9b12d 1524
32a655c1
SL
1525extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1526 LLVMValueRef *Inputs,
1527 unsigned NumInputs) {
9c376795 1528 return new OperandBundleDef(Name, ArrayRef<Value*>(unwrap(Inputs), NumInputs));
7453a54e
SL
1529}
1530
32a655c1 1531extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
7453a54e
SL
1532 delete Bundle;
1533}
1534
e8be2606 1535// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
94222f64 1536extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
32a655c1 1537 LLVMValueRef *Args, unsigned NumArgs,
e8be2606 1538 OperandBundleDef **OpBundlesIndirect,
9c376795 1539 unsigned NumOpBundles) {
f035d41b 1540 Value *Callee = unwrap(Fn);
94222f64 1541 FunctionType *FTy = unwrap<FunctionType>(Ty);
e8be2606
FG
1542
1543 // FIXME: Is there a way around this?
1544 SmallVector<OperandBundleDef> OpBundles;
1545 OpBundles.reserve(NumOpBundles);
1546 for (unsigned i = 0; i < NumOpBundles; ++i) {
1547 OpBundles.push_back(*OpBundlesIndirect[i]);
1548 }
1549
32a655c1 1550 return wrap(unwrap(B)->CreateCall(
9c376795 1551 FTy, Callee, ArrayRef<Value*>(unwrap(Args), NumArgs),
e8be2606 1552 ArrayRef<OperandBundleDef>(OpBundles)));
f035d41b
XL
1553}
1554
3dfed10e 1555extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
e8be2606
FG
1556 return wrap(llvm::Intrinsic::getDeclaration(
1557 unwrap(M), llvm::Intrinsic::instrprof_increment));
1558}
1559
1560extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) {
1561#if LLVM_VERSION_GE(18, 0)
1562 return wrap(llvm::Intrinsic::getDeclaration(
1563 unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters));
1564#else
1565 report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
1566#endif
1567}
1568
1569extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) {
1570#if LLVM_VERSION_GE(18, 0)
1571 return wrap(llvm::Intrinsic::getDeclaration(
1572 unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update));
1573#else
1574 report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
1575#endif
1576}
1577
1578extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) {
1579#if LLVM_VERSION_GE(18, 0)
1580 return wrap(llvm::Intrinsic::getDeclaration(
1581 unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update));
1582#else
1583 report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
1584#endif
7453a54e
SL
1585}
1586
a1dfa0c6
XL
1587extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1588 LLVMValueRef Dst, unsigned DstAlign,
1589 LLVMValueRef Src, unsigned SrcAlign,
1590 LLVMValueRef Size, bool IsVolatile) {
dfeec247
XL
1591 return wrap(unwrap(B)->CreateMemCpy(
1592 unwrap(Dst), MaybeAlign(DstAlign),
1593 unwrap(Src), MaybeAlign(SrcAlign),
1594 unwrap(Size), IsVolatile));
a1dfa0c6
XL
1595}
1596
1597extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1598 LLVMValueRef Dst, unsigned DstAlign,
1599 LLVMValueRef Src, unsigned SrcAlign,
1600 LLVMValueRef Size, bool IsVolatile) {
dfeec247
XL
1601 return wrap(unwrap(B)->CreateMemMove(
1602 unwrap(Dst), MaybeAlign(DstAlign),
1603 unwrap(Src), MaybeAlign(SrcAlign),
1604 unwrap(Size), IsVolatile));
a1dfa0c6
XL
1605}
1606
74b04a01
XL
1607extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1608 LLVMValueRef Dst, unsigned DstAlign,
1609 LLVMValueRef Val,
1610 LLVMValueRef Size, bool IsVolatile) {
ba9703b0
XL
1611 return wrap(unwrap(B)->CreateMemSet(
1612 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
74b04a01
XL
1613}
1614
e8be2606 1615// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
7453a54e 1616extern "C" LLVMValueRef
94222f64
XL
1617LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1618 LLVMValueRef *Args, unsigned NumArgs,
1619 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
e8be2606 1620 OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
9c376795 1621 const char *Name) {
f035d41b 1622 Value *Callee = unwrap(Fn);
94222f64 1623 FunctionType *FTy = unwrap<FunctionType>(Ty);
e8be2606
FG
1624
1625 // FIXME: Is there a way around this?
1626 SmallVector<OperandBundleDef> OpBundles;
1627 OpBundles.reserve(NumOpBundles);
1628 for (unsigned i = 0; i < NumOpBundles; ++i) {
1629 OpBundles.push_back(*OpBundlesIndirect[i]);
1630 }
1631
f035d41b 1632 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
9c376795 1633 ArrayRef<Value*>(unwrap(Args), NumArgs),
e8be2606 1634 ArrayRef<OperandBundleDef>(OpBundles),
9c376795 1635 Name));
7453a54e 1636}
54a0048b 1637
e8be2606 1638// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
c620b35d
FG
1639extern "C" LLVMValueRef
1640LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1641 LLVMBasicBlockRef DefaultDest,
1642 LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
1643 LLVMValueRef *Args, unsigned NumArgs,
e8be2606 1644 OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
c620b35d
FG
1645 const char *Name) {
1646 Value *Callee = unwrap(Fn);
1647 FunctionType *FTy = unwrap<FunctionType>(Ty);
1648
1649 // FIXME: Is there a way around this?
1650 std::vector<BasicBlock*> IndirectDestsUnwrapped;
1651 IndirectDestsUnwrapped.reserve(NumIndirectDests);
1652 for (unsigned i = 0; i < NumIndirectDests; ++i) {
1653 IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i]));
1654 }
1655
e8be2606
FG
1656 // FIXME: Is there a way around this?
1657 SmallVector<OperandBundleDef> OpBundles;
1658 OpBundles.reserve(NumOpBundles);
1659 for (unsigned i = 0; i < NumOpBundles; ++i) {
1660 OpBundles.push_back(*OpBundlesIndirect[i]);
1661 }
1662
c620b35d
FG
1663 return wrap(unwrap(B)->CreateCallBr(
1664 FTy, Callee, unwrap(DefaultDest),
1665 ArrayRef<BasicBlock*>(IndirectDestsUnwrapped),
1666 ArrayRef<Value*>(unwrap(Args), NumArgs),
e8be2606 1667 ArrayRef<OperandBundleDef>(OpBundles),
c620b35d
FG
1668 Name));
1669}
1670
32a655c1
SL
1671extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1672 LLVMBasicBlockRef BB) {
1673 auto Point = unwrap(BB)->getFirstInsertionPt();
1674 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
54a0048b
SL
1675}
1676
32a655c1 1677extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
60c5eb7d 1678 const char *Name, size_t NameLen) {
c620b35d 1679 Triple TargetTriple = Triple(unwrap(M)->getTargetTriple());
32a655c1 1680 GlobalObject *GV = unwrap<GlobalObject>(V);
fc512014 1681 if (TargetTriple.supportsCOMDAT()) {
60c5eb7d
XL
1682 StringRef NameRef(Name, NameLen);
1683 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
32a655c1 1684 }
54a0048b
SL
1685}
1686
9e0c209e 1687enum class LLVMRustLinkage {
32a655c1
SL
1688 ExternalLinkage = 0,
1689 AvailableExternallyLinkage = 1,
1690 LinkOnceAnyLinkage = 2,
1691 LinkOnceODRLinkage = 3,
1692 WeakAnyLinkage = 4,
1693 WeakODRLinkage = 5,
1694 AppendingLinkage = 6,
1695 InternalLinkage = 7,
1696 PrivateLinkage = 8,
1697 ExternalWeakLinkage = 9,
1698 CommonLinkage = 10,
9e0c209e
SL
1699};
1700
32a655c1
SL
1701static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1702 switch (Linkage) {
1703 case LLVMExternalLinkage:
1704 return LLVMRustLinkage::ExternalLinkage;
1705 case LLVMAvailableExternallyLinkage:
1706 return LLVMRustLinkage::AvailableExternallyLinkage;
1707 case LLVMLinkOnceAnyLinkage:
1708 return LLVMRustLinkage::LinkOnceAnyLinkage;
1709 case LLVMLinkOnceODRLinkage:
1710 return LLVMRustLinkage::LinkOnceODRLinkage;
1711 case LLVMWeakAnyLinkage:
1712 return LLVMRustLinkage::WeakAnyLinkage;
1713 case LLVMWeakODRLinkage:
1714 return LLVMRustLinkage::WeakODRLinkage;
1715 case LLVMAppendingLinkage:
1716 return LLVMRustLinkage::AppendingLinkage;
1717 case LLVMInternalLinkage:
1718 return LLVMRustLinkage::InternalLinkage;
1719 case LLVMPrivateLinkage:
1720 return LLVMRustLinkage::PrivateLinkage;
1721 case LLVMExternalWeakLinkage:
1722 return LLVMRustLinkage::ExternalWeakLinkage;
1723 case LLVMCommonLinkage:
1724 return LLVMRustLinkage::CommonLinkage;
1725 default:
ff7c6d11 1726 report_fatal_error("Invalid LLVMRustLinkage value!");
32a655c1 1727 }
9e0c209e
SL
1728}
1729
32a655c1
SL
1730static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1731 switch (Linkage) {
1732 case LLVMRustLinkage::ExternalLinkage:
1733 return LLVMExternalLinkage;
1734 case LLVMRustLinkage::AvailableExternallyLinkage:
1735 return LLVMAvailableExternallyLinkage;
1736 case LLVMRustLinkage::LinkOnceAnyLinkage:
1737 return LLVMLinkOnceAnyLinkage;
1738 case LLVMRustLinkage::LinkOnceODRLinkage:
1739 return LLVMLinkOnceODRLinkage;
1740 case LLVMRustLinkage::WeakAnyLinkage:
1741 return LLVMWeakAnyLinkage;
1742 case LLVMRustLinkage::WeakODRLinkage:
1743 return LLVMWeakODRLinkage;
1744 case LLVMRustLinkage::AppendingLinkage:
1745 return LLVMAppendingLinkage;
1746 case LLVMRustLinkage::InternalLinkage:
1747 return LLVMInternalLinkage;
1748 case LLVMRustLinkage::PrivateLinkage:
1749 return LLVMPrivateLinkage;
1750 case LLVMRustLinkage::ExternalWeakLinkage:
1751 return LLVMExternalWeakLinkage;
1752 case LLVMRustLinkage::CommonLinkage:
1753 return LLVMCommonLinkage;
1754 }
ff7c6d11 1755 report_fatal_error("Invalid LLVMRustLinkage value!");
9e0c209e
SL
1756}
1757
1758extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
32a655c1 1759 return toRust(LLVMGetLinkage(V));
9e0c209e
SL
1760}
1761
32a655c1
SL
1762extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1763 LLVMRustLinkage RustLinkage) {
1764 LLVMSetLinkage(V, fromRust(RustLinkage));
1765}
1766
f2b60f7d
FG
1767extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) {
1768 auto C = unwrap<llvm::ConstantInt>(CV);
1769 if (C->getBitWidth() > 64)
1770 return false;
1771 *value = C->getZExtValue();
1772 return true;
1773}
1774
32a655c1
SL
1775// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1776// the common sizes (1, 8, 16, 32, 64, 128 bits)
1777extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1778{
1779 auto C = unwrap<llvm::ConstantInt>(CV);
1780 if (C->getBitWidth() > 128) { return false; }
1781 APInt AP;
923072b8
FG
1782 if (sext) {
1783 AP = C->getValue().sext(128);
1784 } else {
1785 AP = C->getValue().zext(128);
1786 }
32a655c1
SL
1787 *low = AP.getLoBits(64).getZExtValue();
1788 *high = AP.getHiBits(64).getZExtValue();
1789 return true;
9e0c209e 1790}
476ff2be 1791
476ff2be 1792enum class LLVMRustVisibility {
32a655c1
SL
1793 Default = 0,
1794 Hidden = 1,
1795 Protected = 2,
476ff2be
SL
1796};
1797
32a655c1
SL
1798static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1799 switch (Vis) {
1800 case LLVMDefaultVisibility:
1801 return LLVMRustVisibility::Default;
1802 case LLVMHiddenVisibility:
1803 return LLVMRustVisibility::Hidden;
1804 case LLVMProtectedVisibility:
1805 return LLVMRustVisibility::Protected;
1806 }
ff7c6d11 1807 report_fatal_error("Invalid LLVMRustVisibility value!");
476ff2be
SL
1808}
1809
32a655c1
SL
1810static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1811 switch (Vis) {
1812 case LLVMRustVisibility::Default:
1813 return LLVMDefaultVisibility;
1814 case LLVMRustVisibility::Hidden:
1815 return LLVMHiddenVisibility;
1816 case LLVMRustVisibility::Protected:
1817 return LLVMProtectedVisibility;
1818 }
ff7c6d11 1819 report_fatal_error("Invalid LLVMRustVisibility value!");
476ff2be
SL
1820}
1821
1822extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
32a655c1 1823 return toRust(LLVMGetVisibility(V));
476ff2be
SL
1824}
1825
32a655c1
SL
1826extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1827 LLVMRustVisibility RustVisibility) {
1828 LLVMSetVisibility(V, fromRust(RustVisibility));
476ff2be 1829}
ea8adc8c 1830
cdc7bbd5
XL
1831extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1832 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1833}
1834
ea8adc8c
XL
1835struct LLVMRustModuleBuffer {
1836 std::string data;
1837};
1838
1839extern "C" LLVMRustModuleBuffer*
1840LLVMRustModuleBufferCreate(LLVMModuleRef M) {
dfeec247 1841 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
ea8adc8c 1842 {
c620b35d 1843 auto OS = raw_string_ostream(Ret->data);
2b03887a 1844 WriteBitcodeToFile(*unwrap(M), OS);
ea8adc8c
XL
1845 }
1846 return Ret.release();
1847}
1848
1849extern "C" void
1850LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1851 delete Buffer;
1852}
1853
1854extern "C" const void*
1855LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1856 return Buffer->data.data();
1857}
1858
1859extern "C" size_t
1860LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1861 return Buffer->data.length();
1862}
1863
1864extern "C" uint64_t
1865LLVMRustModuleCost(LLVMModuleRef M) {
2c00a5a8
XL
1866 auto f = unwrap(M)->functions();
1867 return std::distance(std::begin(f), std::end(f));
ea8adc8c 1868}
0531ce1d 1869
9ffffee4
FG
1870extern "C" void
1871LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str)
1872{
c620b35d
FG
1873 auto OS = RawRustStringOstream(Str);
1874 auto JOS = llvm::json::OStream(OS);
9ffffee4
FG
1875 auto Module = unwrap(M);
1876
1877 JOS.object([&] {
1878 JOS.attribute("module", Module->getName());
1879 JOS.attribute("total", Module->getInstructionCount());
1880 });
1881}
1882
0531ce1d 1883// Vector reductions:
0531ce1d
XL
1884extern "C" LLVMValueRef
1885LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1886 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1887}
1888extern "C" LLVMValueRef
1889LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1890 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1891}
1892extern "C" LLVMValueRef
1893LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1894 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1895}
1896extern "C" LLVMValueRef
1897LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1898 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1899}
1900extern "C" LLVMValueRef
1901LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1902 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1903}
1904extern "C" LLVMValueRef
1905LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1906 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1907}
1908extern "C" LLVMValueRef
1909LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1910 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1911}
1912extern "C" LLVMValueRef
1913LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1914 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1915}
1916extern "C" LLVMValueRef
1917LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1918 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1919}
1920extern "C" LLVMValueRef
1921LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
6a06907d
XL
1922 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1923 I->setHasNoNaNs(NoNaN);
1924 return wrap(I);
0531ce1d
XL
1925}
1926extern "C" LLVMValueRef
1927LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
6a06907d
XL
1928 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1929 I->setHasNoNaNs(NoNaN);
1930 return wrap(I);
0531ce1d
XL
1931}
1932
0531ce1d
XL
1933extern "C" LLVMValueRef
1934LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1935 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1936}
1937extern "C" LLVMValueRef
1938LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1939 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1940}
17df50a5
XL
1941
1942// This struct contains all necessary info about a symbol exported from a DLL.
17df50a5
XL
1943struct LLVMRustCOFFShortExport {
1944 const char* name;
c295e0f8
XL
1945 bool ordinal_present;
1946 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1947 uint16_t ordinal;
17df50a5
XL
1948};
1949
1950// Machine must be a COFF machine type, as defined in PE specs.
1951extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1952 const char* ImportName,
1953 const char* Path,
1954 const LLVMRustCOFFShortExport* Exports,
1955 size_t NumExports,
1956 uint16_t Machine,
1957 bool MinGW)
1958{
1959 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1960 ConvertedExports.reserve(NumExports);
1961
1962 for (size_t i = 0; i < NumExports; ++i) {
c295e0f8
XL
1963 bool ordinal_present = Exports[i].ordinal_present;
1964 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
17df50a5
XL
1965 ConvertedExports.push_back(llvm::object::COFFShortExport{
1966 Exports[i].name, // Name
1967 std::string{}, // ExtName
1968 std::string{}, // SymbolName
1969 std::string{}, // AliasTarget
c620b35d
FG
1970#if LLVM_VERSION_GE(19, 0)
1971 std::string{}, // ExportAs
1972#endif
c295e0f8
XL
1973 ordinal, // Ordinal
1974 ordinal_present, // Noname
17df50a5
XL
1975 false, // Data
1976 false, // Private
1977 false // Constant
1978 });
1979 }
1980
1981 auto Error = llvm::object::writeImportLibrary(
1982 ImportName,
1983 Path,
1984 ConvertedExports,
1985 static_cast<llvm::COFF::MachineTypes>(Machine),
1986 MinGW);
1987 if (Error) {
1988 std::string errorString;
c620b35d 1989 auto stream = llvm::raw_string_ostream(errorString);
17df50a5
XL
1990 stream << Error;
1991 stream.flush();
1992 LLVMRustSetLastError(errorString.c_str());
1993 return LLVMRustResult::Failure;
1994 } else {
1995 return LLVMRustResult::Success;
1996 }
1997}
a2a8927a
XL
1998
1999// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
2000extern "C" DiagnosticHandler *
2001LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
2002 std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
2003 return DH.release();
2004}
2005
2006// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
2007// handling. Ownership of the handler is moved to the LLVMContext.
2008extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
2009 DiagnosticHandler *DH) {
2010 unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
2011}
2012
2013using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
2014
2015// Configures a diagnostic handler that invokes provided callback when a
2016// backend needs to emit a diagnostic.
2017//
2018// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
2019// the RemarkPasses array specifies individual passes for which remarks will be
2020// enabled.
fe692bf9
FG
2021//
2022// If RemarkFilePath is not NULL, optimization remarks will be streamed directly into this file,
2023// bypassing the diagnostics handler.
a2a8927a
XL
2024extern "C" void LLVMRustContextConfigureDiagnosticHandler(
2025 LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
2026 void *DiagnosticHandlerContext, bool RemarkAllPasses,
fe692bf9 2027 const char * const * RemarkPasses, size_t RemarkPassesLen,
add651ee
FG
2028 const char * RemarkFilePath,
2029 bool PGOAvailable
fe692bf9 2030) {
a2a8927a
XL
2031
2032 class RustDiagnosticHandler final : public DiagnosticHandler {
2033 public:
fe692bf9
FG
2034 RustDiagnosticHandler(
2035 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
2036 void *DiagnosticHandlerContext,
2037 bool RemarkAllPasses,
2038 std::vector<std::string> RemarkPasses,
2039 std::unique_ptr<ToolOutputFile> RemarksFile,
2040 std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer,
2041 std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer
2042 )
a2a8927a
XL
2043 : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
2044 DiagnosticHandlerContext(DiagnosticHandlerContext),
2045 RemarkAllPasses(RemarkAllPasses),
fe692bf9
FG
2046 RemarkPasses(std::move(RemarkPasses)),
2047 RemarksFile(std::move(RemarksFile)),
2048 RemarkStreamer(std::move(RemarkStreamer)),
2049 LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {}
a2a8927a
XL
2050
2051 virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
add651ee
FG
2052 // If this diagnostic is one of the optimization remark kinds, we can check if it's enabled
2053 // before emitting it. This can avoid many short-lived allocations when unpacking the
2054 // diagnostic and converting its various C++ strings into rust strings.
2055 // FIXME: some diagnostic infos still allocate before we get here, and avoiding that would be
2056 // good in the future. That will require changing a few call sites in LLVM.
2057 if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) {
2058 if (OptDiagBase->isEnabled()) {
2059 if (this->LlvmRemarkStreamer) {
fe692bf9
FG
2060 this->LlvmRemarkStreamer->emit(*OptDiagBase);
2061 return true;
2062 }
add651ee
FG
2063 } else {
2064 return true;
fe692bf9
FG
2065 }
2066 }
a2a8927a 2067 if (DiagnosticHandlerCallback) {
e8be2606
FG
2068#if LLVM_VERSION_GE(19, 0)
2069 DiagnosticHandlerCallback(&DI, DiagnosticHandlerContext);
2070#else
a2a8927a 2071 DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
e8be2606 2072#endif
a2a8927a
XL
2073 return true;
2074 }
2075 return false;
2076 }
2077
2078 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
2079 return isRemarkEnabled(PassName);
2080 }
2081
2082 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
2083 return isRemarkEnabled(PassName);
2084 }
2085
2086 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
2087 return isRemarkEnabled(PassName);
2088 }
2089
2090 bool isAnyRemarkEnabled() const override {
2091 return RemarkAllPasses || !RemarkPasses.empty();
2092 }
2093
2094 private:
2095 bool isRemarkEnabled(StringRef PassName) const {
2096 if (RemarkAllPasses)
2097 return true;
2098
2099 for (auto &Pass : RemarkPasses)
2100 if (Pass == PassName)
2101 return true;
2102
2103 return false;
2104 }
2105
2106 LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
2107 void *DiagnosticHandlerContext = nullptr;
2108
2109 bool RemarkAllPasses = false;
2110 std::vector<std::string> RemarkPasses;
fe692bf9
FG
2111
2112 // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the ordering of the three
2113 // members below is important.
2114 std::unique_ptr<ToolOutputFile> RemarksFile;
2115 std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer;
2116 std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer;
a2a8927a
XL
2117 };
2118
2119 std::vector<std::string> Passes;
2120 for (size_t I = 0; I != RemarkPassesLen; ++I)
fe692bf9 2121 {
a2a8927a 2122 Passes.push_back(RemarkPasses[I]);
fe692bf9
FG
2123 }
2124
2125 // We need to hold onto both the streamers and the opened file
2126 std::unique_ptr<ToolOutputFile> RemarkFile;
2127 std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer;
2128 std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer;
2129
2130 if (RemarkFilePath != nullptr) {
add651ee
FG
2131 if (PGOAvailable) {
2132 // Enable PGO hotness data for remarks, if available
2133 unwrap(C)->setDiagnosticsHotnessRequested(true);
2134 }
2135
fe692bf9
FG
2136 std::error_code EC;
2137 RemarkFile = std::make_unique<ToolOutputFile>(
2138 RemarkFilePath,
2139 EC,
2140 llvm::sys::fs::OF_TextWithCRLF
2141 );
2142 if (EC) {
2143 std::string Error = std::string("Cannot create remark file: ") +
2144 toString(errorCodeToError(EC));
2145 report_fatal_error(Twine(Error));
2146 }
2147
2148 // Do not delete the file after we gather remarks
2149 RemarkFile->keep();
2150
2151 auto RemarkSerializer = remarks::createRemarkSerializer(
2152 llvm::remarks::Format::YAML,
2153 remarks::SerializerMode::Separate,
2154 RemarkFile->os()
2155 );
2156 if (Error E = RemarkSerializer.takeError())
2157 {
2158 std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E));
2159 report_fatal_error(Twine(Error));
2160 }
2161 RemarkStreamer = std::make_unique<llvm::remarks::RemarkStreamer>(std::move(*RemarkSerializer));
2162 LlvmRemarkStreamer = std::make_unique<LLVMRemarkStreamer>(*RemarkStreamer);
2163 }
a2a8927a
XL
2164
2165 unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
fe692bf9
FG
2166 DiagnosticHandlerCallback,
2167 DiagnosticHandlerContext,
2168 RemarkAllPasses,
2169 Passes,
2170 std::move(RemarkFile),
2171 std::move(RemarkStreamer),
2172 std::move(LlvmRemarkStreamer)
2173 ));
a2a8927a 2174}
04454e1e
FG
2175
2176extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
c620b35d 2177 auto OS = RawRustStringOstream(Str);
04454e1e
FG
2178 GlobalValue *GV = unwrap<GlobalValue>(V);
2179 Mangler().getNameWithPrefix(OS, GV, true);
2180}
064997fb 2181
064997fb 2182extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
064997fb
FG
2183 auto *CB = unwrap<CallBase>(CallSite);
2184 switch (CB->getIntrinsicID()) {
2185 case Intrinsic::arm_ldrex:
2186 return 0;
2187 case Intrinsic::arm_strex:
2188 return 1;
2189 }
064997fb
FG
2190 return -1;
2191}
487cf647
FG
2192
2193extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) {
2194 return identify_magic(StringRef(ptr, len)) == file_magic::bitcode;
2195}
add651ee
FG
2196
2197extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) {
2198 if (unwrap<Value>(V)->getType()->isPointerTy()) {
2199 if (auto *GV = dyn_cast<GlobalValue>(unwrap<Value>(V))) {
2200 if (GV->getValueType()->isFunctionTy())
2201 return false;
2202 }
2203 return true;
2204 }
2205 return false;
2206}
781aab86
FG
2207
2208extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() {
781aab86 2209 return llvm::compression::zlib::isAvailable();
781aab86
FG
2210}
2211
2212extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
781aab86 2213 return llvm::compression::zstd::isAvailable();
781aab86 2214}
c620b35d
FG
2215
2216// Operations on composite constants.
2217// These are clones of LLVM api functions that will become available in future releases.
2218// They can be removed once Rust's minimum supported LLVM version supports them.
2219// See https://github.com/rust-lang/rust/issues/121868
2220// See https://llvm.org/doxygen/group__LLVMCCoreValueConstantComposite.html
2221
2222// FIXME: Remove when Rust's minimum supported LLVM version reaches 19.
2223// https://github.com/llvm/llvm-project/commit/e1405e4f71c899420ebf8262d5e9745598419df8
2224#if LLVM_VERSION_LT(19, 0)
2225extern "C" LLVMValueRef LLVMConstStringInContext2(LLVMContextRef C,
2226 const char *Str,
2227 size_t Length,
2228 bool DontNullTerminate) {
2229 return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), !DontNullTerminate));
2230}
2231#endif