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