]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_llvm / llvm-wrapper / RustWrapper.cpp
CommitLineData
1b1a35ee 1#include "LLVMWrapper.h"
cc61c64b 2#include "llvm/IR/DebugInfoMetadata.h"
1a4d82fc
JJ
3#include "llvm/IR/DiagnosticInfo.h"
4#include "llvm/IR/DiagnosticPrinter.h"
b7449926 5#include "llvm/IR/GlobalVariable.h"
5bcae85e 6#include "llvm/IR/Instructions.h"
f035d41b 7#include "llvm/IR/Intrinsics.h"
32a655c1 8#include "llvm/Object/Archive.h"
17df50a5 9#include "llvm/Object/COFFImportFile.h"
32a655c1 10#include "llvm/Object/ObjectFile.h"
ea8adc8c 11#include "llvm/Bitcode/BitcodeWriterPass.h"
0bf4aa26 12#include "llvm/Support/Signals.h"
3b2f2976 13#include "llvm/ADT/Optional.h"
3b2f2976 14
0bf4aa26
XL
15#include <iostream>
16
223e47cc
LB
17//===----------------------------------------------------------------------===
18//
19// This file defines alternate interfaces to core functions that are more
20// readily callable by Rust's FFI.
21//
22//===----------------------------------------------------------------------===
23
223e47cc
LB
24using namespace llvm;
25using namespace llvm::sys;
1a4d82fc 26using namespace llvm::object;
223e47cc 27
5bcae85e
SL
28// LLVMAtomicOrdering is already an enum - don't create another
29// one.
32a655c1 30static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
5bcae85e 31 switch (Ordering) {
32a655c1
SL
32 case LLVMAtomicOrderingNotAtomic:
33 return AtomicOrdering::NotAtomic;
34 case LLVMAtomicOrderingUnordered:
35 return AtomicOrdering::Unordered;
36 case LLVMAtomicOrderingMonotonic:
37 return AtomicOrdering::Monotonic;
38 case LLVMAtomicOrderingAcquire:
39 return AtomicOrdering::Acquire;
40 case LLVMAtomicOrderingRelease:
41 return AtomicOrdering::Release;
42 case LLVMAtomicOrderingAcquireRelease:
43 return AtomicOrdering::AcquireRelease;
44 case LLVMAtomicOrderingSequentiallyConsistent:
45 return AtomicOrdering::SequentiallyConsistent;
5bcae85e
SL
46 }
47
ff7c6d11 48 report_fatal_error("Invalid LLVMAtomicOrdering value!");
5bcae85e
SL
49}
50
abe05a73 51static LLVM_THREAD_LOCAL char *LastError;
970d7e83 52
0bf4aa26
XL
53// Custom error handler for fatal LLVM errors.
54//
55// Notably it exits the process with code 101, unlike LLVM's default of 1.
56static void FatalErrorHandler(void *UserData,
c295e0f8 57#if LLVM_VERSION_LT(14, 0)
0bf4aa26 58 const std::string& Reason,
c295e0f8
XL
59#else
60 const char* Reason,
61#endif
0bf4aa26
XL
62 bool GenCrashDiag) {
63 // Do the same thing that the default error handler does.
64 std::cerr << "LLVM ERROR: " << Reason << std::endl;
65
66 // Since this error handler exits the process, we have to run any cleanup that
67 // LLVM would run after handling the error. This might change with an LLVM
68 // upgrade.
69 sys::RunInterruptHandlers();
70
71 exit(101);
72}
73
74extern "C" void LLVMRustInstallFatalErrorHandler() {
75 install_fatal_error_handler(FatalErrorHandler);
76}
77
1a4d82fc 78extern "C" char *LLVMRustGetLastError(void) {
32a655c1
SL
79 char *Ret = LastError;
80 LastError = nullptr;
81 return Ret;
223e47cc
LB
82}
83
60c5eb7d
XL
84extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
85 return unwrap(M)->getInstructionCount();
86}
87
ff7c6d11 88extern "C" void LLVMRustSetLastError(const char *Err) {
32a655c1
SL
89 free((void *)LastError);
90 LastError = strdup(Err);
223e47cc
LB
91}
92
ff7c6d11
XL
93extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
94 auto ctx = new LLVMContext();
95 ctx->setDiscardValueNames(shouldDiscardNames);
96 return wrap(ctx);
97}
98
32a655c1
SL
99extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
100 const char *Triple) {
101 unwrap(M)->setTargetTriple(Triple::normalize(Triple));
223e47cc
LB
102}
103
223e47cc 104extern "C" void LLVMRustPrintPassTimings() {
32a655c1 105 raw_fd_ostream OS(2, false); // stderr.
223e47cc
LB
106 TimerGroup::printAll(OS);
107}
108
ba9703b0
XL
109extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
110 size_t NameLen) {
111 return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
9346a6ac
AL
112}
113
5bcae85e 114extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
32a655c1 115 const char *Name,
ba9703b0 116 size_t NameLen,
32a655c1 117 LLVMTypeRef FunctionTy) {
ba9703b0
XL
118 return wrap(unwrap(M)
119 ->getOrInsertFunction(StringRef(Name, NameLen),
120 unwrap<FunctionType>(FunctionTy))
ba9703b0 121 .getCallee()
ba9703b0 122 );
223e47cc
LB
123}
124
32a655c1 125extern "C" LLVMValueRef
60c5eb7d
XL
126LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
127 StringRef NameRef(Name, NameLen);
128 return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
9346a6ac
AL
129}
130
b7449926
XL
131extern "C" LLVMValueRef
132LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
133 return wrap(new GlobalVariable(*unwrap(M),
134 unwrap(Ty),
135 false,
136 GlobalValue::PrivateLinkage,
137 nullptr));
138}
139
5bcae85e 140extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
223e47cc
LB
141 return wrap(Type::getMetadataTy(*unwrap(C)));
142}
970d7e83 143
32a655c1
SL
144static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
145 switch (Kind) {
146 case AlwaysInline:
147 return Attribute::AlwaysInline;
148 case ByVal:
149 return Attribute::ByVal;
150 case Cold:
151 return Attribute::Cold;
152 case InlineHint:
153 return Attribute::InlineHint;
154 case MinSize:
155 return Attribute::MinSize;
156 case Naked:
157 return Attribute::Naked;
158 case NoAlias:
159 return Attribute::NoAlias;
160 case NoCapture:
161 return Attribute::NoCapture;
162 case NoInline:
163 return Attribute::NoInline;
164 case NonNull:
165 return Attribute::NonNull;
166 case NoRedZone:
167 return Attribute::NoRedZone;
168 case NoReturn:
169 return Attribute::NoReturn;
170 case NoUnwind:
171 return Attribute::NoUnwind;
172 case OptimizeForSize:
173 return Attribute::OptimizeForSize;
174 case ReadOnly:
175 return Attribute::ReadOnly;
176 case SExt:
177 return Attribute::SExt;
178 case StructRet:
179 return Attribute::StructRet;
180 case UWTable:
181 return Attribute::UWTable;
182 case ZExt:
183 return Attribute::ZExt;
184 case InReg:
185 return Attribute::InReg;
8bb4bdeb
XL
186 case SanitizeThread:
187 return Attribute::SanitizeThread;
188 case SanitizeAddress:
189 return Attribute::SanitizeAddress;
190 case SanitizeMemory:
191 return Attribute::SanitizeMemory;
0bf4aa26
XL
192 case NonLazyBind:
193 return Attribute::NonLazyBind;
9fa01778
XL
194 case OptimizeNone:
195 return Attribute::OptimizeNone;
196 case ReturnsTwice:
197 return Attribute::ReturnsTwice;
f9f354fc
XL
198 case ReadNone:
199 return Attribute::ReadNone;
200 case InaccessibleMemOnly:
201 return Attribute::InaccessibleMemOnly;
6a06907d
XL
202 case SanitizeHWAddress:
203 return Attribute::SanitizeHWAddress;
204 case WillReturn:
205 return Attribute::WillReturn;
476ff2be 206 }
ff7c6d11 207 report_fatal_error("bad AttributeKind");
476ff2be
SL
208}
209
c295e0f8
XL
210template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
211#if LLVM_VERSION_LT(14, 0)
212 t->addAttribute(Index, Attr);
213#else
214 t->addAttributeAtIndex(Index, Attr);
215#endif
216}
217
32a655c1
SL
218extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
219 LLVMRustAttribute RustAttr) {
f035d41b 220 CallBase *Call = unwrap<CallBase>(Instr);
32a655c1 221 Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
c295e0f8 222 AddAttribute(Call, Index, Attr);
1a4d82fc
JJ
223}
224
5869c6ff
XL
225extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
226 const char *Name) {
227 CallBase *Call = unwrap<CallBase>(Instr);
228 Attribute Attr = Attribute::get(Call->getContext(), Name);
c295e0f8 229 AddAttribute(Call, Index, Attr);
5869c6ff
XL
230}
231
ff7c6d11
XL
232extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
233 unsigned Index,
234 uint32_t Bytes) {
f035d41b 235 CallBase *Call = unwrap<CallBase>(Instr);
c295e0f8
XL
236 Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
237 AddAttribute(Call, Index, Attr);
ff7c6d11
XL
238}
239
5bcae85e 240extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
32a655c1
SL
241 unsigned Index,
242 uint64_t Bytes) {
f035d41b 243 CallBase *Call = unwrap<CallBase>(Instr);
c295e0f8
XL
244 Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
245 AddAttribute(Call, Index, Attr);
1a4d82fc 246}
1a4d82fc 247
ff7c6d11
XL
248extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
249 unsigned Index,
250 uint64_t Bytes) {
f035d41b 251 CallBase *Call = unwrap<CallBase>(Instr);
c295e0f8
XL
252 Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
253 AddAttribute(Call, Index, Attr);
ff7c6d11
XL
254}
255
416331ca
XL
256extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
257 LLVMTypeRef Ty) {
f035d41b 258 CallBase *Call = unwrap<CallBase>(Instr);
416331ca 259 Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
c295e0f8 260 AddAttribute(Call, Index, Attr);
416331ca
XL
261}
262
6a06907d
XL
263extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
264 LLVMTypeRef Ty) {
265 CallBase *Call = unwrap<CallBase>(Instr);
266#if LLVM_VERSION_GE(12, 0)
267 Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
268#else
269 Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
270#endif
c295e0f8 271 AddAttribute(Call, Index, Attr);
6a06907d
XL
272}
273
32a655c1
SL
274extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
275 LLVMRustAttribute RustAttr) {
1a4d82fc 276 Function *A = unwrap<Function>(Fn);
32a655c1 277 Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
c295e0f8 278 AddAttribute(A, Index, Attr);
1a4d82fc
JJ
279}
280
ff7c6d11
XL
281extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
282 unsigned Index,
283 uint32_t Bytes) {
284 Function *A = unwrap<Function>(Fn);
c295e0f8 285 AddAttribute(A, Index, Attribute::getWithAlignment(
94222f64 286 A->getContext(), llvm::Align(Bytes)));
ff7c6d11
XL
287}
288
32a655c1
SL
289extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
290 uint64_t Bytes) {
1a4d82fc 291 Function *A = unwrap<Function>(Fn);
c295e0f8 292 AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
94222f64 293 Bytes));
1a4d82fc 294}
1a4d82fc 295
ff7c6d11
XL
296extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
297 unsigned Index,
298 uint64_t Bytes) {
299 Function *A = unwrap<Function>(Fn);
c295e0f8 300 AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
94222f64 301 A->getContext(), Bytes));
ff7c6d11
XL
302}
303
416331ca
XL
304extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
305 LLVMTypeRef Ty) {
306 Function *F = unwrap<Function>(Fn);
416331ca 307 Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
c295e0f8 308 AddAttribute(F, Index, Attr);
416331ca
XL
309}
310
6a06907d
XL
311extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
312 LLVMTypeRef Ty) {
313 Function *F = unwrap<Function>(Fn);
314#if LLVM_VERSION_GE(12, 0)
315 Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty));
316#else
317 Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet);
318#endif
c295e0f8 319 AddAttribute(F, Index, Attr);
6a06907d
XL
320}
321
5bcae85e 322extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
32a655c1
SL
323 unsigned Index,
324 const char *Name,
325 const char *Value) {
62682a34 326 Function *F = unwrap<Function>(Fn);
c295e0f8 327 AddAttribute(F, Index, Attribute::get(
94222f64 328 F->getContext(), StringRef(Name), StringRef(Value)));
62682a34
SL
329}
330
5bcae85e 331extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
32a655c1
SL
332 unsigned Index,
333 LLVMRustAttribute RustAttr) {
476ff2be 334 Function *F = unwrap<Function>(Fn);
32a655c1 335 Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
476ff2be 336 AttrBuilder B(Attr);
3b2f2976 337 auto PAL = F->getAttributes();
c295e0f8
XL
338 AttributeList PALNew;
339#if LLVM_VERSION_LT(14, 0)
340 PALNew = PAL.removeAttributes(F->getContext(), Index, B);
341#else
342 PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B);
343#endif
32a655c1 344 F->setAttributes(PALNew);
1a4d82fc
JJ
345}
346
cdc7bbd5
XL
347// Enable a fast-math flag
348//
349// https://llvm.org/docs/LangRef.html#fast-math-flags
350extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
32a655c1 351 if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
2c00a5a8 352 I->setFast(true);
32a655c1 353 }
54a0048b
SL
354}
355
32a655c1 356extern "C" LLVMValueRef
136023e0
XL
357LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
358 const char *Name, LLVMAtomicOrdering Order) {
f035d41b 359 Value *Ptr = unwrap(Source);
136023e0 360 LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
32a655c1 361 LI->setAtomic(fromRust(Order));
f035d41b 362 return wrap(LI);
970d7e83
LB
363}
364
5bcae85e 365extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
32a655c1
SL
366 LLVMValueRef V,
367 LLVMValueRef Target,
ff7c6d11 368 LLVMAtomicOrdering Order) {
f035d41b 369 StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
32a655c1 370 SI->setAtomic(fromRust(Order));
f035d41b 371 return wrap(SI);
32a655c1
SL
372}
373
f035d41b
XL
374// FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
375// once we raise our minimum support to LLVM 10.
32a655c1
SL
376extern "C" LLVMValueRef
377LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
378 LLVMValueRef Old, LLVMValueRef Source,
379 LLVMAtomicOrdering Order,
380 LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
cdc7bbd5
XL
381#if LLVM_VERSION_GE(13,0)
382 // Rust probably knows the alignment of the target value and should be able to
383 // specify something more precise than MaybeAlign here. See also
384 // https://reviews.llvm.org/D97224 which may be a useful reference.
385 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
386 unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
387 fromRust(FailureOrder));
388#else
32a655c1
SL
389 AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
390 unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
391 fromRust(FailureOrder));
cdc7bbd5 392#endif
32a655c1
SL
393 ACXI->setWeak(Weak);
394 return wrap(ACXI);
223e47cc 395}
5bcae85e
SL
396
397enum class LLVMRustSynchronizationScope {
32a655c1
SL
398 SingleThread,
399 CrossThread,
5bcae85e
SL
400};
401
3b2f2976
XL
402static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
403 switch (Scope) {
404 case LLVMRustSynchronizationScope::SingleThread:
405 return SyncScope::SingleThread;
406 case LLVMRustSynchronizationScope::CrossThread:
407 return SyncScope::System;
408 default:
ff7c6d11 409 report_fatal_error("bad SynchronizationScope.");
3b2f2976
XL
410 }
411}
223e47cc 412
32a655c1
SL
413extern "C" LLVMValueRef
414LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
415 LLVMRustSynchronizationScope Scope) {
416 return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
5bcae85e
SL
417}
418
5bcae85e 419enum class LLVMRustAsmDialect {
32a655c1
SL
420 Att,
421 Intel,
5bcae85e
SL
422};
423
32a655c1
SL
424static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
425 switch (Dialect) {
426 case LLVMRustAsmDialect::Att:
427 return InlineAsm::AD_ATT;
428 case LLVMRustAsmDialect::Intel:
429 return InlineAsm::AD_Intel;
430 default:
ff7c6d11 431 report_fatal_error("bad AsmDialect.");
32a655c1 432 }
5bcae85e
SL
433}
434
ba9703b0
XL
435extern "C" LLVMValueRef
436LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
437 char *Constraints, size_t ConstraintsLen,
438 LLVMBool HasSideEffects, LLVMBool IsAlignStack,
439 LLVMRustAsmDialect Dialect) {
440 return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
441 StringRef(AsmString, AsmStringLen),
442 StringRef(Constraints, ConstraintsLen),
32a655c1 443 HasSideEffects, IsAlignStack, fromRust(Dialect)));
223e47cc 444}
970d7e83 445
ba9703b0
XL
446extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
447 size_t ConstraintsLen) {
448 return InlineAsm::Verify(unwrap<FunctionType>(Ty),
449 StringRef(Constraints, ConstraintsLen));
0bf4aa26
XL
450}
451
ba9703b0
XL
452extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
453 size_t AsmLen) {
454 unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
cc61c64b
XL
455}
456
32a655c1 457typedef DIBuilder *LLVMRustDIBuilderRef;
970d7e83 458
3b2f2976 459template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
32a655c1 460 return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
62682a34
SL
461}
462
62682a34
SL
463#define DIDescriptor DIScope
464#define DIArray DINodeArray
32a655c1 465#define unwrapDI unwrapDIPtr
62682a34 466
476ff2be
SL
467// These values **must** match debuginfo::DIFlags! They also *happen*
468// to match LLVM, but that isn't required as we do giant sets of
469// matching below. The value shouldn't be directly passed to LLVM.
470enum class LLVMRustDIFlags : uint32_t {
32a655c1
SL
471 FlagZero = 0,
472 FlagPrivate = 1,
473 FlagProtected = 2,
474 FlagPublic = 3,
475 FlagFwdDecl = (1 << 2),
476 FlagAppleBlock = (1 << 3),
477 FlagBlockByrefStruct = (1 << 4),
478 FlagVirtual = (1 << 5),
479 FlagArtificial = (1 << 6),
480 FlagExplicit = (1 << 7),
481 FlagPrototyped = (1 << 8),
482 FlagObjcClassComplete = (1 << 9),
483 FlagObjectPointer = (1 << 10),
484 FlagVector = (1 << 11),
485 FlagStaticMember = (1 << 12),
486 FlagLValueReference = (1 << 13),
487 FlagRValueReference = (1 << 14),
2c00a5a8
XL
488 FlagExternalTypeRef = (1 << 15),
489 FlagIntroducedVirtual = (1 << 18),
490 FlagBitField = (1 << 19),
491 FlagNoReturn = (1 << 20),
32a655c1 492 // Do not add values that are not supported by the minimum LLVM
2c00a5a8 493 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
476ff2be
SL
494};
495
32a655c1
SL
496inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
497 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
498 static_cast<uint32_t>(B));
476ff2be
SL
499}
500
32a655c1
SL
501inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
502 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
503 static_cast<uint32_t>(B));
476ff2be
SL
504}
505
32a655c1
SL
506inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
507 return A = A | B;
476ff2be
SL
508}
509
32a655c1 510inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
476ff2be 511
32a655c1
SL
512inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
513 return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
476ff2be
SL
514}
515
32a655c1
SL
516static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
517 DINode::DIFlags Result = DINode::DIFlags::FlagZero;
476ff2be 518
32a655c1
SL
519 switch (visibility(Flags)) {
520 case LLVMRustDIFlags::FlagPrivate:
521 Result |= DINode::DIFlags::FlagPrivate;
522 break;
523 case LLVMRustDIFlags::FlagProtected:
524 Result |= DINode::DIFlags::FlagProtected;
525 break;
526 case LLVMRustDIFlags::FlagPublic:
527 Result |= DINode::DIFlags::FlagPublic;
528 break;
529 default:
530 // The rest are handled below
531 break;
532 }
476ff2be 533
32a655c1
SL
534 if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
535 Result |= DINode::DIFlags::FlagFwdDecl;
536 }
537 if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
538 Result |= DINode::DIFlags::FlagAppleBlock;
539 }
32a655c1
SL
540 if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
541 Result |= DINode::DIFlags::FlagVirtual;
542 }
543 if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
544 Result |= DINode::DIFlags::FlagArtificial;
545 }
546 if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
547 Result |= DINode::DIFlags::FlagExplicit;
548 }
549 if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
550 Result |= DINode::DIFlags::FlagPrototyped;
551 }
552 if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
553 Result |= DINode::DIFlags::FlagObjcClassComplete;
554 }
555 if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
556 Result |= DINode::DIFlags::FlagObjectPointer;
557 }
558 if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
559 Result |= DINode::DIFlags::FlagVector;
560 }
561 if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
562 Result |= DINode::DIFlags::FlagStaticMember;
563 }
564 if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
565 Result |= DINode::DIFlags::FlagLValueReference;
566 }
567 if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
568 Result |= DINode::DIFlags::FlagRValueReference;
569 }
2c00a5a8
XL
570 if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
571 Result |= DINode::DIFlags::FlagIntroducedVirtual;
572 }
573 if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
574 Result |= DINode::DIFlags::FlagBitField;
575 }
2c00a5a8
XL
576 if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
577 Result |= DINode::DIFlags::FlagNoReturn;
578 }
476ff2be 579
32a655c1 580 return Result;
476ff2be
SL
581}
582
9fa01778
XL
583// These values **must** match debuginfo::DISPFlags! They also *happen*
584// to match LLVM, but that isn't required as we do giant sets of
585// matching below. The value shouldn't be directly passed to LLVM.
586enum class LLVMRustDISPFlags : uint32_t {
587 SPFlagZero = 0,
588 SPFlagVirtual = 1,
589 SPFlagPureVirtual = 2,
590 SPFlagLocalToUnit = (1 << 2),
591 SPFlagDefinition = (1 << 3),
592 SPFlagOptimized = (1 << 4),
532ac7d7 593 SPFlagMainSubprogram = (1 << 5),
9fa01778
XL
594 // Do not add values that are not supported by the minimum LLVM
595 // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
596 // (In LLVM < 8, createFunction supported these as separate bool arguments.)
597};
598
599inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
600 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
601 static_cast<uint32_t>(B));
602}
603
604inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
605 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
606 static_cast<uint32_t>(B));
607}
608
609inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
610 return A = A | B;
611}
612
613inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
614
615inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
616 return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
617}
618
9fa01778
XL
619static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
620 DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
621
622 switch (virtuality(SPFlags)) {
623 case LLVMRustDISPFlags::SPFlagVirtual:
624 Result |= DISubprogram::DISPFlags::SPFlagVirtual;
625 break;
626 case LLVMRustDISPFlags::SPFlagPureVirtual:
627 Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
628 break;
629 default:
630 // The rest are handled below
631 break;
632 }
633
634 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
635 Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
636 }
637 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
638 Result |= DISubprogram::DISPFlags::SPFlagDefinition;
639 }
640 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
641 Result |= DISubprogram::DISPFlags::SPFlagOptimized;
642 }
532ac7d7
XL
643 if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
644 Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
645 }
9fa01778
XL
646
647 return Result;
648}
9fa01778
XL
649
650enum class LLVMRustDebugEmissionKind {
651 NoDebug,
652 FullDebug,
653 LineTablesOnly,
654};
655
656static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
657 switch (Kind) {
658 case LLVMRustDebugEmissionKind::NoDebug:
659 return DICompileUnit::DebugEmissionKind::NoDebug;
660 case LLVMRustDebugEmissionKind::FullDebug:
661 return DICompileUnit::DebugEmissionKind::FullDebug;
662 case LLVMRustDebugEmissionKind::LineTablesOnly:
663 return DICompileUnit::DebugEmissionKind::LineTablesOnly;
664 default:
665 report_fatal_error("bad DebugEmissionKind.");
666 }
667}
668
ba9703b0
XL
669enum class LLVMRustChecksumKind {
670 None,
671 MD5,
672 SHA1,
29967ef6 673 SHA256,
ba9703b0
XL
674};
675
676static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
677 switch (Kind) {
678 case LLVMRustChecksumKind::None:
679 return None;
680 case LLVMRustChecksumKind::MD5:
681 return DIFile::ChecksumKind::CSK_MD5;
682 case LLVMRustChecksumKind::SHA1:
683 return DIFile::ChecksumKind::CSK_SHA1;
29967ef6
XL
684#if (LLVM_VERSION_MAJOR >= 11)
685 case LLVMRustChecksumKind::SHA256:
686 return DIFile::ChecksumKind::CSK_SHA256;
687#endif
ba9703b0
XL
688 default:
689 report_fatal_error("bad ChecksumKind.");
690 }
691}
692
62682a34 693extern "C" uint32_t LLVMRustDebugMetadataVersion() {
32a655c1 694 return DEBUG_METADATA_VERSION;
62682a34
SL
695}
696
5869c6ff
XL
697extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
698
32a655c1 699extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
62682a34 700
32a655c1 701extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
1a4d82fc 702
32a655c1
SL
703extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
704 uint32_t Value) {
705 unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
970d7e83
LB
706}
707
ff7c6d11
XL
708extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
709 return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
041b39d2
XL
710}
711
5bcae85e 712extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
32a655c1 713 return new DIBuilder(*unwrap(M));
970d7e83
LB
714}
715
5bcae85e 716extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
32a655c1 717 delete Builder;
970d7e83
LB
718}
719
5bcae85e 720extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
32a655c1 721 Builder->finalize();
970d7e83
LB
722}
723
3b2f2976
XL
724extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
725 LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
74b04a01
XL
726 const char *Producer, size_t ProducerLen, bool isOptimized,
727 const char *Flags, unsigned RuntimeVer,
728 const char *SplitName, size_t SplitNameLen,
fc512014
XL
729 LLVMRustDebugEmissionKind Kind,
730 uint64_t DWOId, bool SplitDebugInlining) {
8bb4bdeb
XL
731 auto *File = unwrapDI<DIFile>(FileRef);
732
74b04a01
XL
733 return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
734 isOptimized, Flags, RuntimeVer,
735 StringRef(SplitName, SplitNameLen),
fc512014 736 fromRust(Kind), DWOId, SplitDebugInlining));
32a655c1
SL
737}
738
74b04a01
XL
739extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
740 LLVMRustDIBuilderRef Builder,
741 const char *Filename, size_t FilenameLen,
ba9703b0
XL
742 const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
743 const char *Checksum, size_t ChecksumLen) {
744 Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
745 Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
746 if (llvmCSKind)
747 CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
74b04a01 748 return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
ba9703b0
XL
749 StringRef(Directory, DirectoryLen),
750 CSInfo));
32a655c1
SL
751}
752
3b2f2976 753extern "C" LLVMMetadataRef
32a655c1 754LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
3b2f2976 755 LLVMMetadataRef ParameterTypes) {
32a655c1 756 return wrap(Builder->createSubroutineType(
32a655c1 757 DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
970d7e83
LB
758}
759
3b2f2976 760extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
74b04a01
XL
761 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
762 const char *Name, size_t NameLen,
763 const char *LinkageName, size_t LinkageNameLen,
764 LLVMMetadataRef File, unsigned LineNo,
9fa01778 765 LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
29967ef6 766 LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
9fa01778 767 LLVMMetadataRef Decl) {
32a655c1
SL
768 DITemplateParameterArray TParams =
769 DITemplateParameterArray(unwrap<MDTuple>(TParam));
532ac7d7
XL
770 DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
771 DINode::DIFlags llvmFlags = fromRust(Flags);
9fa01778 772 DISubprogram *Sub = Builder->createFunction(
74b04a01
XL
773 unwrapDI<DIScope>(Scope),
774 StringRef(Name, NameLen),
775 StringRef(LinkageName, LinkageNameLen),
776 unwrapDI<DIFile>(File), LineNo,
777 unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
532ac7d7 778 llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
29967ef6
XL
779 if (MaybeFn)
780 unwrap<Function>(MaybeFn)->setSubprogram(Sub);
32a655c1 781 return wrap(Sub);
970d7e83
LB
782}
783
74b04a01
XL
784extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
785 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
f9f354fc 786 uint64_t SizeInBits, unsigned Encoding) {
74b04a01 787 return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
970d7e83 788}
1a4d82fc 789
f035d41b
XL
790extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
791 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
792 LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
793 return wrap(Builder->createTypedef(
794 unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
29967ef6 795 LineNo, unwrapDIPtr<DIScope>(Scope)));
f035d41b
XL
796}
797
3b2f2976
XL
798extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
799 LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
74b04a01
XL
800 uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
801 const char *Name, size_t NameLen) {
32a655c1 802 return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
3b2f2976 803 SizeInBits, AlignInBits,
74b04a01
XL
804 AddressSpace,
805 StringRef(Name, NameLen)));
970d7e83
LB
806}
807
3b2f2976 808extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
74b04a01
XL
809 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
810 const char *Name, size_t NameLen,
3b2f2976 811 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
8bb4bdeb 812 uint32_t AlignInBits, LLVMRustDIFlags Flags,
3b2f2976
XL
813 LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
814 unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
74b04a01 815 const char *UniqueId, size_t UniqueIdLen) {
32a655c1 816 return wrap(Builder->createStructType(
74b04a01
XL
817 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
818 unwrapDI<DIFile>(File), LineNumber,
32a655c1
SL
819 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
820 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
74b04a01 821 unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
970d7e83
LB
822}
823
a1dfa0c6 824extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
74b04a01
XL
825 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
826 const char *Name, size_t NameLen,
a1dfa0c6
XL
827 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
828 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
74b04a01 829 LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
a1dfa0c6 830 return wrap(Builder->createVariantPart(
74b04a01
XL
831 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
832 unwrapDI<DIFile>(File), LineNumber,
a1dfa0c6 833 SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
74b04a01 834 DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
a1dfa0c6
XL
835}
836
3b2f2976 837extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
74b04a01
XL
838 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
839 const char *Name, size_t NameLen,
3b2f2976 840 LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
8bb4bdeb 841 uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
3b2f2976 842 LLVMMetadataRef Ty) {
74b04a01
XL
843 return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
844 StringRef(Name, NameLen),
32a655c1
SL
845 unwrapDI<DIFile>(File), LineNo,
846 SizeInBits, AlignInBits, OffsetInBits,
847 fromRust(Flags), unwrapDI<DIType>(Ty)));
970d7e83 848}
1a4d82fc 849
a1dfa0c6
XL
850extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
851 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
74b04a01
XL
852 const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
853 uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
a1dfa0c6 854 LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
a1dfa0c6
XL
855 llvm::ConstantInt* D = nullptr;
856 if (Discriminant) {
857 D = unwrap<llvm::ConstantInt>(Discriminant);
858 }
74b04a01
XL
859 return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
860 StringRef(Name, NameLen),
a1dfa0c6
XL
861 unwrapDI<DIFile>(File), LineNo,
862 SizeInBits, AlignInBits, OffsetInBits, D,
863 fromRust(Flags), unwrapDI<DIType>(Ty)));
a1dfa0c6
XL
864}
865
3b2f2976
XL
866extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
867 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
868 LLVMMetadataRef File, unsigned Line, unsigned Col) {
32a655c1
SL
869 return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
870 unwrapDI<DIFile>(File), Line, Col));
1a4d82fc
JJ
871}
872
3b2f2976 873extern "C" LLVMMetadataRef
32a655c1 874LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
3b2f2976
XL
875 LLVMMetadataRef Scope,
876 LLVMMetadataRef File) {
32a655c1
SL
877 return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
878 unwrapDI<DIFile>(File)));
9e0c209e
SL
879}
880
3b2f2976 881extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
74b04a01
XL
882 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
883 const char *Name, size_t NameLen,
884 const char *LinkageName, size_t LinkageNameLen,
885 LLVMMetadataRef File, unsigned LineNo,
3b2f2976
XL
886 LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
887 LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
cc61c64b 888 llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
476ff2be 889
32a655c1
SL
890 llvm::DIExpression *InitExpr = nullptr;
891 if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
892 InitExpr = Builder->createConstantValueExpression(
893 IntVal->getValue().getSExtValue());
894 } else if (llvm::ConstantFP *FPVal =
895 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
896 InitExpr = Builder->createConstantValueExpression(
897 FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
898 }
476ff2be 899
cc61c64b 900 llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
74b04a01
XL
901 unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
902 StringRef(LinkageName, LinkageNameLen),
cc61c64b 903 unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
dfeec247 904 /* isDefined */ true,
a1dfa0c6 905 InitExpr, unwrapDIPtr<MDNode>(Decl),
a1dfa0c6 906 /* templateParams */ nullptr,
a1dfa0c6 907 AlignInBits);
cc61c64b
XL
908
909 InitVal->setMetadata("dbg", VarExpr);
910
911 return wrap(VarExpr);
970d7e83 912}
1a4d82fc 913
3b2f2976
XL
914extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
915 LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
74b04a01
XL
916 const char *Name, size_t NameLen,
917 LLVMMetadataRef File, unsigned LineNo,
3b2f2976 918 LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
8bb4bdeb 919 unsigned ArgNo, uint32_t AlignInBits) {
32a655c1
SL
920 if (Tag == 0x100) { // DW_TAG_auto_variable
921 return wrap(Builder->createAutoVariable(
74b04a01
XL
922 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
923 unwrapDI<DIFile>(File), LineNo,
8faf50e0 924 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
32a655c1
SL
925 } else {
926 return wrap(Builder->createParameterVariable(
74b04a01
XL
927 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
928 unwrapDI<DIFile>(File), LineNo,
929 unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
32a655c1 930 }
970d7e83
LB
931}
932
3b2f2976 933extern "C" LLVMMetadataRef
32a655c1 934LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
3b2f2976
XL
935 uint32_t AlignInBits, LLVMMetadataRef Ty,
936 LLVMMetadataRef Subscripts) {
32a655c1
SL
937 return wrap(
938 Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
939 DINodeArray(unwrapDI<MDTuple>(Subscripts))));
970d7e83
LB
940}
941
3b2f2976 942extern "C" LLVMMetadataRef
32a655c1
SL
943LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
944 int64_t Count) {
945 return wrap(Builder->getOrCreateSubrange(Lo, Count));
970d7e83
LB
946}
947
3b2f2976 948extern "C" LLVMMetadataRef
32a655c1 949LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
3b2f2976 950 LLVMMetadataRef *Ptr, unsigned Count) {
32a655c1
SL
951 Metadata **DataValue = unwrap(Ptr);
952 return wrap(
953 Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
970d7e83
LB
954}
955
5bcae85e 956extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
3b2f2976 957 LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
29967ef6 958 int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
970d7e83 959 LLVMBasicBlockRef InsertAtEnd) {
32a655c1
SL
960 return wrap(Builder->insertDeclare(
961 unwrap(V), unwrap<DILocalVariable>(VarInfo),
962 Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
29967ef6 963 DebugLoc(cast<MDNode>(unwrap(DL))),
32a655c1
SL
964 unwrap(InsertAtEnd)));
965}
966
74b04a01
XL
967extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
968 LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
969 int64_t Value, bool IsUnsigned) {
970 return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
1a4d82fc
JJ
971}
972
3b2f2976 973extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
74b04a01
XL
974 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
975 const char *Name, size_t NameLen,
3b2f2976
XL
976 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
977 uint32_t AlignInBits, LLVMMetadataRef Elements,
9fa01778 978 LLVMMetadataRef ClassTy, bool IsScoped) {
a1dfa0c6 979 return wrap(Builder->createEnumerationType(
74b04a01
XL
980 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
981 unwrapDI<DIFile>(File), LineNumber,
a1dfa0c6 982 SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
9fa01778 983 unwrapDI<DIType>(ClassTy), "", IsScoped));
1a4d82fc
JJ
984}
985
3b2f2976 986extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
74b04a01
XL
987 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
988 const char *Name, size_t NameLen,
3b2f2976
XL
989 LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
990 uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
74b04a01 991 unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
32a655c1 992 return wrap(Builder->createUnionType(
74b04a01
XL
993 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
994 LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
995 DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
996 StringRef(UniqueId, UniqueIdLen)));
1a4d82fc
JJ
997}
998
3b2f2976 999extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
74b04a01 1000 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
f9f354fc 1001 const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
f035d41b
XL
1002#if LLVM_VERSION_GE(11, 0)
1003 bool IsDefault = false; // FIXME: should we ever set this true?
1004 return wrap(Builder->createTemplateTypeParameter(
1005 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
1006#else
32a655c1 1007 return wrap(Builder->createTemplateTypeParameter(
74b04a01 1008 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
f035d41b 1009#endif
32a655c1
SL
1010}
1011
74b04a01
XL
1012extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
1013 LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
1014 const char *Name, size_t NameLen, bool ExportSymbols) {
32a655c1 1015 return wrap(Builder->createNameSpace(
74b04a01
XL
1016 unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
1017 ));
1a4d82fc
JJ
1018}
1019
32a655c1 1020extern "C" void
a1dfa0c6
XL
1021LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
1022 LLVMMetadataRef CompositeTy,
1023 LLVMMetadataRef Elements,
1024 LLVMMetadataRef Params) {
32a655c1 1025 DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
a1dfa0c6
XL
1026 Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
1027 DINodeArray(unwrap<MDTuple>(Params)));
1a4d82fc
JJ
1028}
1029
29967ef6 1030extern "C" LLVMMetadataRef
5869c6ff 1031LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
6a06907d 1032 LLVMMetadataRef ScopeRef,
3b2f2976 1033 LLVMMetadataRef InlinedAt) {
6a06907d
XL
1034#if LLVM_VERSION_GE(12, 0)
1035 MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
1036 DILocation *Loc = DILocation::get(
1037 Scope->getContext(), Line, Column, Scope,
1038 unwrapDIPtr<MDNode>(InlinedAt));
1039 return wrap(Loc);
1040#else
1041 DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(ScopeRef),
32a655c1 1042 unwrapDIPtr<MDNode>(InlinedAt));
29967ef6 1043 return wrap(debug_loc.getAsMDNode());
6a06907d 1044#endif
85aaf69f
SL
1045}
1046
32a655c1
SL
1047extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
1048 return dwarf::DW_OP_deref;
5bcae85e
SL
1049}
1050
2c00a5a8 1051extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
2c00a5a8 1052 return dwarf::DW_OP_plus_uconst;
2c00a5a8 1053}
5bcae85e 1054
32a655c1
SL
1055extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
1056 RawRustStringOstream OS(Str);
1057 unwrap<llvm::Type>(Ty)->print(OS);
1a4d82fc
JJ
1058}
1059
32a655c1
SL
1060extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
1061 RustStringRef Str) {
1062 RawRustStringOstream OS(Str);
7cac9316
XL
1063 if (!V) {
1064 OS << "(null)";
1065 } else {
1066 OS << "(";
1067 unwrap<llvm::Value>(V)->getType()->print(OS);
1068 OS << ":";
1069 unwrap<llvm::Value>(V)->print(OS);
1070 OS << ")";
1071 }
1a4d82fc
JJ
1072}
1073
1a4d82fc 1074// LLVMArrayType function does not support 64-bit ElementCount
32a655c1
SL
1075extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
1076 uint64_t ElementCount) {
1077 return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
1a4d82fc
JJ
1078}
1079
1080DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
1a4d82fc 1081
32a655c1
SL
1082extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
1083 RawRustStringOstream OS(Str);
1084 unwrap(T)->print(OS);
1a4d82fc
JJ
1085}
1086
32a655c1
SL
1087extern "C" void LLVMRustUnpackOptimizationDiagnostic(
1088 LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
3b2f2976
XL
1089 LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
1090 RustStringRef FilenameOut, RustStringRef MessageOut) {
32a655c1
SL
1091 // Undefined to call this not on an optimization diagnostic!
1092 llvm::DiagnosticInfoOptimizationBase *Opt =
1093 static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
1a4d82fc 1094
32a655c1
SL
1095 RawRustStringOstream PassNameOS(PassNameOut);
1096 PassNameOS << Opt->getPassName();
1097 *FunctionOut = wrap(&Opt->getFunction());
3b2f2976
XL
1098
1099 RawRustStringOstream FilenameOS(FilenameOut);
3b2f2976
XL
1100 DiagnosticLocation loc = Opt->getLocation();
1101 if (loc.isValid()) {
1102 *Line = loc.getLine();
1103 *Column = loc.getColumn();
9fa01778 1104 FilenameOS << loc.getAbsolutePath();
3b2f2976 1105 }
3b2f2976 1106
32a655c1
SL
1107 RawRustStringOstream MessageOS(MessageOut);
1108 MessageOS << Opt->getMsg();
1a4d82fc
JJ
1109}
1110
f035d41b
XL
1111enum class LLVMRustDiagnosticLevel {
1112 Error,
1113 Warning,
1114 Note,
1115 Remark,
1116};
1117
85aaf69f 1118extern "C" void
f035d41b
XL
1119LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1120 LLVMRustDiagnosticLevel *LevelOut,
1121 unsigned *CookieOut,
94222f64 1122 LLVMTwineRef *MessageOut) {
32a655c1
SL
1123 // Undefined to call this not on an inline assembly diagnostic!
1124 llvm::DiagnosticInfoInlineAsm *IA =
1125 static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
85aaf69f 1126
32a655c1
SL
1127 *CookieOut = IA->getLocCookie();
1128 *MessageOut = wrap(&IA->getMsgStr());
f035d41b
XL
1129
1130 switch (IA->getSeverity()) {
1131 case DS_Error:
1132 *LevelOut = LLVMRustDiagnosticLevel::Error;
1133 break;
1134 case DS_Warning:
1135 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1136 break;
1137 case DS_Note:
1138 *LevelOut = LLVMRustDiagnosticLevel::Note;
1139 break;
1140 case DS_Remark:
1141 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1142 break;
1143 default:
1144 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1145 }
85aaf69f
SL
1146}
1147
32a655c1
SL
1148extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
1149 RustStringRef Str) {
1150 RawRustStringOstream OS(Str);
1151 DiagnosticPrinterRawOStream DP(OS);
1152 unwrap(DI)->print(DP);
1a4d82fc
JJ
1153}
1154
5bcae85e 1155enum class LLVMRustDiagnosticKind {
32a655c1
SL
1156 Other,
1157 InlineAsm,
1158 StackSize,
1159 DebugMetadataVersion,
1160 SampleProfile,
1161 OptimizationRemark,
1162 OptimizationRemarkMissed,
1163 OptimizationRemarkAnalysis,
1164 OptimizationRemarkAnalysisFPCommute,
1165 OptimizationRemarkAnalysisAliasing,
1166 OptimizationRemarkOther,
1167 OptimizationFailure,
0531ce1d 1168 PGOProfile,
b7449926 1169 Linker,
1b1a35ee 1170 Unsupported,
94222f64 1171 SrcMgr,
5bcae85e
SL
1172};
1173
32a655c1
SL
1174static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
1175 switch (Kind) {
1176 case DK_InlineAsm:
1177 return LLVMRustDiagnosticKind::InlineAsm;
1178 case DK_StackSize:
1179 return LLVMRustDiagnosticKind::StackSize;
1180 case DK_DebugMetadataVersion:
1181 return LLVMRustDiagnosticKind::DebugMetadataVersion;
1182 case DK_SampleProfile:
1183 return LLVMRustDiagnosticKind::SampleProfile;
1184 case DK_OptimizationRemark:
1185 return LLVMRustDiagnosticKind::OptimizationRemark;
1186 case DK_OptimizationRemarkMissed:
1187 return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
1188 case DK_OptimizationRemarkAnalysis:
1189 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
32a655c1
SL
1190 case DK_OptimizationRemarkAnalysisFPCommute:
1191 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
1192 case DK_OptimizationRemarkAnalysisAliasing:
1193 return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
0531ce1d
XL
1194 case DK_PGOProfile:
1195 return LLVMRustDiagnosticKind::PGOProfile;
b7449926
XL
1196 case DK_Linker:
1197 return LLVMRustDiagnosticKind::Linker;
1b1a35ee
XL
1198 case DK_Unsupported:
1199 return LLVMRustDiagnosticKind::Unsupported;
94222f64
XL
1200#if LLVM_VERSION_GE(13, 0)
1201 case DK_SrcMgr:
1202 return LLVMRustDiagnosticKind::SrcMgr;
1203#endif
32a655c1 1204 default:
32a655c1
SL
1205 return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
1206 ? LLVMRustDiagnosticKind::OptimizationRemarkOther
1207 : LLVMRustDiagnosticKind::Other;
5bcae85e
SL
1208 }
1209}
1210
32a655c1
SL
1211extern "C" LLVMRustDiagnosticKind
1212LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
1213 return toRust((DiagnosticKind)unwrap(DI)->getKind());
5bcae85e 1214}
f035d41b 1215
5bcae85e
SL
1216// This is kept distinct from LLVMGetTypeKind, because when
1217// a new type kind is added, the Rust-side enum must be
1218// updated or UB will result.
1219extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
1220 switch (unwrap(Ty)->getTypeID()) {
1221 case Type::VoidTyID:
1222 return LLVMVoidTypeKind;
1223 case Type::HalfTyID:
1224 return LLVMHalfTypeKind;
1225 case Type::FloatTyID:
1226 return LLVMFloatTypeKind;
1227 case Type::DoubleTyID:
1228 return LLVMDoubleTypeKind;
1229 case Type::X86_FP80TyID:
1230 return LLVMX86_FP80TypeKind;
1231 case Type::FP128TyID:
1232 return LLVMFP128TypeKind;
1233 case Type::PPC_FP128TyID:
1234 return LLVMPPC_FP128TypeKind;
1235 case Type::LabelTyID:
1236 return LLVMLabelTypeKind;
1237 case Type::MetadataTyID:
1238 return LLVMMetadataTypeKind;
1239 case Type::IntegerTyID:
1240 return LLVMIntegerTypeKind;
1241 case Type::FunctionTyID:
1242 return LLVMFunctionTypeKind;
1243 case Type::StructTyID:
1244 return LLVMStructTypeKind;
1245 case Type::ArrayTyID:
1246 return LLVMArrayTypeKind;
1247 case Type::PointerTyID:
1248 return LLVMPointerTypeKind;
f035d41b
XL
1249#if LLVM_VERSION_GE(11, 0)
1250 case Type::FixedVectorTyID:
1251 return LLVMVectorTypeKind;
1252#else
5bcae85e
SL
1253 case Type::VectorTyID:
1254 return LLVMVectorTypeKind;
f035d41b 1255#endif
5bcae85e
SL
1256 case Type::X86_MMXTyID:
1257 return LLVMX86_MMXTypeKind;
5bcae85e
SL
1258 case Type::TokenTyID:
1259 return LLVMTokenTypeKind;
f035d41b
XL
1260#if LLVM_VERSION_GE(11, 0)
1261 case Type::ScalableVectorTyID:
1262 return LLVMScalableVectorTypeKind;
1263 case Type::BFloatTyID:
1264 return LLVMBFloatTypeKind;
6a06907d
XL
1265#endif
1266#if LLVM_VERSION_GE(12, 0)
1267 case Type::X86_AMXTyID:
1268 return LLVMX86_AMXTypeKind;
f035d41b 1269#endif
5bcae85e 1270 }
ff7c6d11 1271 report_fatal_error("Unhandled TypeID.");
1a4d82fc
JJ
1272}
1273
1a4d82fc
JJ
1274DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
1275
cdc7bbd5
XL
1276#if LLVM_VERSION_LT(13, 0)
1277using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
1278#else
1279using LLVMInlineAsmDiagHandlerTy = void*;
1280#endif
1281
5bcae85e 1282extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
cdc7bbd5
XL
1283 LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
1284 // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
1285 // with LLVM 13 this function is gone.
1286#if LLVM_VERSION_LT(13, 0)
32a655c1 1287 unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
cdc7bbd5 1288#endif
1a4d82fc
JJ
1289}
1290
94222f64
XL
1291extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1292 LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1293#if LLVM_VERSION_GE(13, 0)
1294 llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1295 *Cookie = SM->getLocCookie();
1296 return wrap(&SM->getSMDiag());
1297#else
1298 report_fatal_error("Shouldn't get called on older versions");
1299#endif
1300}
1301
f9f354fc
XL
1302extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
1303 RustStringRef MessageOut,
1304 RustStringRef BufferOut,
f035d41b 1305 LLVMRustDiagnosticLevel* LevelOut,
f9f354fc
XL
1306 unsigned* LocOut,
1307 unsigned* RangesOut,
1308 size_t* NumRanges) {
1309 SMDiagnostic& D = *unwrap(DRef);
1310 RawRustStringOstream MessageOS(MessageOut);
1311 MessageOS << D.getMessage();
1312
f035d41b
XL
1313 switch (D.getKind()) {
1314 case SourceMgr::DK_Error:
1315 *LevelOut = LLVMRustDiagnosticLevel::Error;
1316 break;
1317 case SourceMgr::DK_Warning:
1318 *LevelOut = LLVMRustDiagnosticLevel::Warning;
1319 break;
1320 case SourceMgr::DK_Note:
1321 *LevelOut = LLVMRustDiagnosticLevel::Note;
1322 break;
1323 case SourceMgr::DK_Remark:
1324 *LevelOut = LLVMRustDiagnosticLevel::Remark;
1325 break;
1326 default:
1327 report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1328 }
1329
f9f354fc
XL
1330 if (D.getLoc() == SMLoc())
1331 return false;
1332
1333 const SourceMgr &LSM = *D.getSourceMgr();
1334 const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
1335 LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
1336
1337 *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
1338
1339 *NumRanges = std::min(*NumRanges, D.getRanges().size());
1340 size_t LineStart = *LocOut - (size_t)D.getColumnNo();
1341 for (size_t i = 0; i < *NumRanges; i++) {
1342 RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
1343 RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
1344 }
1345
1346 return true;
1a4d82fc 1347}
c1a9b12d 1348
32a655c1
SL
1349extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
1350 LLVMValueRef ParentPad,
1351 unsigned ArgCount,
1352 LLVMValueRef *LLArgs,
1353 const char *Name) {
32a655c1
SL
1354 Value **Args = unwrap(LLArgs);
1355 if (ParentPad == nullptr) {
1356 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1357 ParentPad = wrap(Constant::getNullValue(Ty));
1358 }
1359 return wrap(unwrap(B)->CreateCleanupPad(
1360 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
7453a54e
SL
1361}
1362
32a655c1
SL
1363extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
1364 LLVMValueRef CleanupPad,
1365 LLVMBasicBlockRef UnwindBB) {
32a655c1
SL
1366 CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
1367 return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
7453a54e
SL
1368}
1369
1370extern "C" LLVMValueRef
32a655c1
SL
1371LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
1372 unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
32a655c1
SL
1373 Value **Args = unwrap(LLArgs);
1374 return wrap(unwrap(B)->CreateCatchPad(
1375 unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
7453a54e
SL
1376}
1377
32a655c1
SL
1378extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
1379 LLVMValueRef Pad,
1380 LLVMBasicBlockRef BB) {
32a655c1
SL
1381 return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
1382 unwrap(BB)));
7453a54e
SL
1383}
1384
32a655c1
SL
1385extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
1386 LLVMValueRef ParentPad,
1387 LLVMBasicBlockRef BB,
1388 unsigned NumHandlers,
1389 const char *Name) {
32a655c1
SL
1390 if (ParentPad == nullptr) {
1391 Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
1392 ParentPad = wrap(Constant::getNullValue(Ty));
1393 }
1394 return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
1395 NumHandlers, Name));
7453a54e
SL
1396}
1397
32a655c1
SL
1398extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
1399 LLVMBasicBlockRef Handler) {
32a655c1
SL
1400 Value *CatchSwitch = unwrap(CatchSwitchRef);
1401 cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
7453a54e
SL
1402}
1403
32a655c1
SL
1404extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
1405 LLVMValueRef *Inputs,
1406 unsigned NumInputs) {
7453a54e
SL
1407 return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
1408}
1409
32a655c1 1410extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
7453a54e
SL
1411 delete Bundle;
1412}
1413
94222f64 1414extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
32a655c1 1415 LLVMValueRef *Args, unsigned NumArgs,
ba9703b0 1416 OperandBundleDef *Bundle) {
f035d41b 1417 Value *Callee = unwrap(Fn);
94222f64 1418 FunctionType *FTy = unwrap<FunctionType>(Ty);
32a655c1
SL
1419 unsigned Len = Bundle ? 1 : 0;
1420 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
1421 return wrap(unwrap(B)->CreateCall(
f035d41b
XL
1422 FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
1423}
1424
3dfed10e 1425extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
f035d41b
XL
1426 return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
1427 (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
7453a54e
SL
1428}
1429
a1dfa0c6
XL
1430extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
1431 LLVMValueRef Dst, unsigned DstAlign,
1432 LLVMValueRef Src, unsigned SrcAlign,
1433 LLVMValueRef Size, bool IsVolatile) {
dfeec247
XL
1434 return wrap(unwrap(B)->CreateMemCpy(
1435 unwrap(Dst), MaybeAlign(DstAlign),
1436 unwrap(Src), MaybeAlign(SrcAlign),
1437 unwrap(Size), IsVolatile));
a1dfa0c6
XL
1438}
1439
1440extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
1441 LLVMValueRef Dst, unsigned DstAlign,
1442 LLVMValueRef Src, unsigned SrcAlign,
1443 LLVMValueRef Size, bool IsVolatile) {
dfeec247
XL
1444 return wrap(unwrap(B)->CreateMemMove(
1445 unwrap(Dst), MaybeAlign(DstAlign),
1446 unwrap(Src), MaybeAlign(SrcAlign),
1447 unwrap(Size), IsVolatile));
a1dfa0c6
XL
1448}
1449
74b04a01
XL
1450extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
1451 LLVMValueRef Dst, unsigned DstAlign,
1452 LLVMValueRef Val,
1453 LLVMValueRef Size, bool IsVolatile) {
ba9703b0
XL
1454 return wrap(unwrap(B)->CreateMemSet(
1455 unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
74b04a01
XL
1456}
1457
7453a54e 1458extern "C" LLVMValueRef
94222f64
XL
1459LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
1460 LLVMValueRef *Args, unsigned NumArgs,
1461 LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
1462 OperandBundleDef *Bundle, const char *Name) {
f035d41b 1463 Value *Callee = unwrap(Fn);
94222f64 1464 FunctionType *FTy = unwrap<FunctionType>(Ty);
32a655c1
SL
1465 unsigned Len = Bundle ? 1 : 0;
1466 ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
f035d41b 1467 return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
32a655c1
SL
1468 makeArrayRef(unwrap(Args), NumArgs),
1469 Bundles, Name));
7453a54e 1470}
54a0048b 1471
32a655c1
SL
1472extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
1473 LLVMBasicBlockRef BB) {
1474 auto Point = unwrap(BB)->getFirstInsertionPt();
1475 unwrap(B)->SetInsertPoint(unwrap(BB), Point);
54a0048b
SL
1476}
1477
32a655c1 1478extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
60c5eb7d 1479 const char *Name, size_t NameLen) {
32a655c1
SL
1480 Triple TargetTriple(unwrap(M)->getTargetTriple());
1481 GlobalObject *GV = unwrap<GlobalObject>(V);
fc512014 1482 if (TargetTriple.supportsCOMDAT()) {
60c5eb7d
XL
1483 StringRef NameRef(Name, NameLen);
1484 GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
32a655c1 1485 }
54a0048b
SL
1486}
1487
1488extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
32a655c1
SL
1489 GlobalObject *GV = unwrap<GlobalObject>(V);
1490 GV->setComdat(nullptr);
54a0048b 1491}
9e0c209e
SL
1492
1493enum class LLVMRustLinkage {
32a655c1
SL
1494 ExternalLinkage = 0,
1495 AvailableExternallyLinkage = 1,
1496 LinkOnceAnyLinkage = 2,
1497 LinkOnceODRLinkage = 3,
1498 WeakAnyLinkage = 4,
1499 WeakODRLinkage = 5,
1500 AppendingLinkage = 6,
1501 InternalLinkage = 7,
1502 PrivateLinkage = 8,
1503 ExternalWeakLinkage = 9,
1504 CommonLinkage = 10,
9e0c209e
SL
1505};
1506
32a655c1
SL
1507static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
1508 switch (Linkage) {
1509 case LLVMExternalLinkage:
1510 return LLVMRustLinkage::ExternalLinkage;
1511 case LLVMAvailableExternallyLinkage:
1512 return LLVMRustLinkage::AvailableExternallyLinkage;
1513 case LLVMLinkOnceAnyLinkage:
1514 return LLVMRustLinkage::LinkOnceAnyLinkage;
1515 case LLVMLinkOnceODRLinkage:
1516 return LLVMRustLinkage::LinkOnceODRLinkage;
1517 case LLVMWeakAnyLinkage:
1518 return LLVMRustLinkage::WeakAnyLinkage;
1519 case LLVMWeakODRLinkage:
1520 return LLVMRustLinkage::WeakODRLinkage;
1521 case LLVMAppendingLinkage:
1522 return LLVMRustLinkage::AppendingLinkage;
1523 case LLVMInternalLinkage:
1524 return LLVMRustLinkage::InternalLinkage;
1525 case LLVMPrivateLinkage:
1526 return LLVMRustLinkage::PrivateLinkage;
1527 case LLVMExternalWeakLinkage:
1528 return LLVMRustLinkage::ExternalWeakLinkage;
1529 case LLVMCommonLinkage:
1530 return LLVMRustLinkage::CommonLinkage;
1531 default:
ff7c6d11 1532 report_fatal_error("Invalid LLVMRustLinkage value!");
32a655c1 1533 }
9e0c209e
SL
1534}
1535
32a655c1
SL
1536static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
1537 switch (Linkage) {
1538 case LLVMRustLinkage::ExternalLinkage:
1539 return LLVMExternalLinkage;
1540 case LLVMRustLinkage::AvailableExternallyLinkage:
1541 return LLVMAvailableExternallyLinkage;
1542 case LLVMRustLinkage::LinkOnceAnyLinkage:
1543 return LLVMLinkOnceAnyLinkage;
1544 case LLVMRustLinkage::LinkOnceODRLinkage:
1545 return LLVMLinkOnceODRLinkage;
1546 case LLVMRustLinkage::WeakAnyLinkage:
1547 return LLVMWeakAnyLinkage;
1548 case LLVMRustLinkage::WeakODRLinkage:
1549 return LLVMWeakODRLinkage;
1550 case LLVMRustLinkage::AppendingLinkage:
1551 return LLVMAppendingLinkage;
1552 case LLVMRustLinkage::InternalLinkage:
1553 return LLVMInternalLinkage;
1554 case LLVMRustLinkage::PrivateLinkage:
1555 return LLVMPrivateLinkage;
1556 case LLVMRustLinkage::ExternalWeakLinkage:
1557 return LLVMExternalWeakLinkage;
1558 case LLVMRustLinkage::CommonLinkage:
1559 return LLVMCommonLinkage;
1560 }
ff7c6d11 1561 report_fatal_error("Invalid LLVMRustLinkage value!");
9e0c209e
SL
1562}
1563
1564extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
32a655c1 1565 return toRust(LLVMGetLinkage(V));
9e0c209e
SL
1566}
1567
32a655c1
SL
1568extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
1569 LLVMRustLinkage RustLinkage) {
1570 LLVMSetLinkage(V, fromRust(RustLinkage));
1571}
1572
94222f64
XL
1573extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
1574 LLVMValueRef ConstantVal,
1575 LLVMValueRef *ConstantIndices,
1576 unsigned NumIndices) {
1577 ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1578 NumIndices);
1579 Constant *Val = unwrap<Constant>(ConstantVal);
1580 return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1581}
1582
32a655c1
SL
1583// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
1584// the common sizes (1, 8, 16, 32, 64, 128 bits)
1585extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
1586{
1587 auto C = unwrap<llvm::ConstantInt>(CV);
1588 if (C->getBitWidth() > 128) { return false; }
1589 APInt AP;
1590 if (sext) {
1591 AP = C->getValue().sextOrSelf(128);
1592 } else {
1593 AP = C->getValue().zextOrSelf(128);
1594 }
1595 *low = AP.getLoBits(64).getZExtValue();
1596 *high = AP.getHiBits(64).getZExtValue();
1597 return true;
9e0c209e 1598}
476ff2be 1599
476ff2be 1600enum class LLVMRustVisibility {
32a655c1
SL
1601 Default = 0,
1602 Hidden = 1,
1603 Protected = 2,
476ff2be
SL
1604};
1605
32a655c1
SL
1606static LLVMRustVisibility toRust(LLVMVisibility Vis) {
1607 switch (Vis) {
1608 case LLVMDefaultVisibility:
1609 return LLVMRustVisibility::Default;
1610 case LLVMHiddenVisibility:
1611 return LLVMRustVisibility::Hidden;
1612 case LLVMProtectedVisibility:
1613 return LLVMRustVisibility::Protected;
1614 }
ff7c6d11 1615 report_fatal_error("Invalid LLVMRustVisibility value!");
476ff2be
SL
1616}
1617
32a655c1
SL
1618static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
1619 switch (Vis) {
1620 case LLVMRustVisibility::Default:
1621 return LLVMDefaultVisibility;
1622 case LLVMRustVisibility::Hidden:
1623 return LLVMHiddenVisibility;
1624 case LLVMRustVisibility::Protected:
1625 return LLVMProtectedVisibility;
1626 }
ff7c6d11 1627 report_fatal_error("Invalid LLVMRustVisibility value!");
476ff2be
SL
1628}
1629
1630extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
32a655c1 1631 return toRust(LLVMGetVisibility(V));
476ff2be
SL
1632}
1633
8bb4bdeb
XL
1634// Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
1635extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
1636 LLVMTypeRef DestTy, bool isSigned) {
1637 return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
1638}
1639
32a655c1
SL
1640extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
1641 LLVMRustVisibility RustVisibility) {
1642 LLVMSetVisibility(V, fromRust(RustVisibility));
476ff2be 1643}
ea8adc8c 1644
cdc7bbd5
XL
1645extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
1646 unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
1647}
1648
ea8adc8c
XL
1649struct LLVMRustModuleBuffer {
1650 std::string data;
1651};
1652
1653extern "C" LLVMRustModuleBuffer*
1654LLVMRustModuleBufferCreate(LLVMModuleRef M) {
dfeec247 1655 auto Ret = std::make_unique<LLVMRustModuleBuffer>();
ea8adc8c
XL
1656 {
1657 raw_string_ostream OS(Ret->data);
1658 {
1659 legacy::PassManager PM;
1660 PM.add(createBitcodeWriterPass(OS));
1661 PM.run(*unwrap(M));
1662 }
1663 }
1664 return Ret.release();
1665}
1666
1667extern "C" void
1668LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
1669 delete Buffer;
1670}
1671
1672extern "C" const void*
1673LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
1674 return Buffer->data.data();
1675}
1676
1677extern "C" size_t
1678LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
1679 return Buffer->data.length();
1680}
1681
1682extern "C" uint64_t
1683LLVMRustModuleCost(LLVMModuleRef M) {
2c00a5a8
XL
1684 auto f = unwrap(M)->functions();
1685 return std::distance(std::begin(f), std::end(f));
ea8adc8c 1686}
0531ce1d
XL
1687
1688// Vector reductions:
0531ce1d
XL
1689extern "C" LLVMValueRef
1690LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1691 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
1692}
1693extern "C" LLVMValueRef
1694LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
1695 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
1696}
1697extern "C" LLVMValueRef
1698LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
1699 return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
1700}
1701extern "C" LLVMValueRef
1702LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
1703 return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
1704}
1705extern "C" LLVMValueRef
1706LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
1707 return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
1708}
1709extern "C" LLVMValueRef
1710LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
1711 return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
1712}
1713extern "C" LLVMValueRef
1714LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
1715 return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
1716}
1717extern "C" LLVMValueRef
1718LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1719 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
1720}
1721extern "C" LLVMValueRef
1722LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
1723 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
1724}
1725extern "C" LLVMValueRef
1726LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
6a06907d
XL
1727#if LLVM_VERSION_GE(12, 0)
1728 Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
1729 I->setHasNoNaNs(NoNaN);
1730 return wrap(I);
1731#else
1732 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
1733#endif
0531ce1d
XL
1734}
1735extern "C" LLVMValueRef
1736LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
6a06907d
XL
1737#if LLVM_VERSION_GE(12, 0)
1738 Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
1739 I->setHasNoNaNs(NoNaN);
1740 return wrap(I);
1741#else
0531ce1d 1742 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
6a06907d 1743#endif
0531ce1d
XL
1744}
1745
0531ce1d
XL
1746extern "C" LLVMValueRef
1747LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1748 return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
1749}
1750extern "C" LLVMValueRef
1751LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
1752 return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
1753}
17df50a5
XL
1754
1755// This struct contains all necessary info about a symbol exported from a DLL.
17df50a5
XL
1756struct LLVMRustCOFFShortExport {
1757 const char* name;
c295e0f8
XL
1758 bool ordinal_present;
1759 // The value of `ordinal` is only meaningful if `ordinal_present` is true.
1760 uint16_t ordinal;
17df50a5
XL
1761};
1762
1763// Machine must be a COFF machine type, as defined in PE specs.
1764extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
1765 const char* ImportName,
1766 const char* Path,
1767 const LLVMRustCOFFShortExport* Exports,
1768 size_t NumExports,
1769 uint16_t Machine,
1770 bool MinGW)
1771{
1772 std::vector<llvm::object::COFFShortExport> ConvertedExports;
1773 ConvertedExports.reserve(NumExports);
1774
1775 for (size_t i = 0; i < NumExports; ++i) {
c295e0f8
XL
1776 bool ordinal_present = Exports[i].ordinal_present;
1777 uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
17df50a5
XL
1778 ConvertedExports.push_back(llvm::object::COFFShortExport{
1779 Exports[i].name, // Name
1780 std::string{}, // ExtName
1781 std::string{}, // SymbolName
1782 std::string{}, // AliasTarget
c295e0f8
XL
1783 ordinal, // Ordinal
1784 ordinal_present, // Noname
17df50a5
XL
1785 false, // Data
1786 false, // Private
1787 false // Constant
1788 });
1789 }
1790
1791 auto Error = llvm::object::writeImportLibrary(
1792 ImportName,
1793 Path,
1794 ConvertedExports,
1795 static_cast<llvm::COFF::MachineTypes>(Machine),
1796 MinGW);
1797 if (Error) {
1798 std::string errorString;
1799 llvm::raw_string_ostream stream(errorString);
1800 stream << Error;
1801 stream.flush();
1802 LLVMRustSetLastError(errorString.c_str());
1803 return LLVMRustResult::Failure;
1804 } else {
1805 return LLVMRustResult::Success;
1806 }
1807}