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