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