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