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