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