]> git.lizzy.rs Git - rust.git/blob - src/rustllvm/RustWrapper.cpp
Auto merge of #34155 - ollie27:unzip, r=alexcrichton
[rust.git] / src / rustllvm / RustWrapper.cpp
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #include "rustllvm.h"
12 #include "llvm/Object/Archive.h"
13 #include "llvm/Object/ObjectFile.h"
14 #include "llvm/IR/DiagnosticInfo.h"
15 #include "llvm/IR/DiagnosticPrinter.h"
16
17 #include "llvm/IR/CallSite.h"
18
19 //===----------------------------------------------------------------------===
20 //
21 // This file defines alternate interfaces to core functions that are more
22 // readily callable by Rust's FFI.
23 //
24 //===----------------------------------------------------------------------===
25
26 using namespace llvm;
27 using namespace llvm::sys;
28 using namespace llvm::object;
29
30 static char *LastError;
31
32 extern "C" LLVMMemoryBufferRef
33 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
34   ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(Path,
35                                                                         -1,
36                                                                         false);
37   if (!buf_or) {
38       LLVMRustSetLastError(buf_or.getError().message().c_str());
39       return nullptr;
40   }
41   return wrap(buf_or.get().release());
42 }
43
44 extern "C" char *LLVMRustGetLastError(void) {
45   char *ret = LastError;
46   LastError = NULL;
47   return ret;
48 }
49
50 void LLVMRustSetLastError(const char *err) {
51   free((void*) LastError);
52   LastError = strdup(err);
53 }
54
55 extern "C" void
56 LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) {
57     unwrap(M)->setTargetTriple(Triple::normalize(triple));
58 }
59
60 extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
61                                               LLVMBool SignExtend) {
62   return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
63 }
64
65 extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy,
66            unsigned N_hi,
67            unsigned N_lo,
68            LLVMBool SignExtend) {
69   unsigned long long N = N_hi;
70   N <<= 32;
71   N |= N_lo;
72   return LLVMConstInt(IntTy, N, SignExtend);
73 }
74
75 extern "C" void LLVMRustPrintPassTimings() {
76   raw_fd_ostream OS (2, false); // stderr.
77   TimerGroup::printAll(OS);
78 }
79
80 extern "C" LLVMValueRef LLVMGetNamedValue(LLVMModuleRef M,
81                                           const char* Name) {
82     return wrap(unwrap(M)->getNamedValue(Name));
83 }
84
85 extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
86                                                 const char* Name,
87                                                 LLVMTypeRef FunctionTy) {
88   return wrap(unwrap(M)->getOrInsertFunction(Name,
89                                              unwrap<FunctionType>(FunctionTy)));
90 }
91
92 extern "C" LLVMValueRef LLVMGetOrInsertGlobal(LLVMModuleRef M,
93                                               const char* Name,
94                                               LLVMTypeRef Ty) {
95   return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
96 }
97
98 extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
99   return wrap(Type::getMetadataTy(*unwrap(C)));
100 }
101
102 extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
103   CallSite Call = CallSite(unwrap<Instruction>(Instr));
104   AttrBuilder B;
105   B.addRawValue(Val);
106   Call.setAttributes(
107     Call.getAttributes().addAttributes(Call->getContext(), index,
108                                        AttributeSet::get(Call->getContext(),
109                                                          index, B)));
110 }
111
112
113 extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) {
114   CallSite Call = CallSite(unwrap<Instruction>(Instr));
115   AttrBuilder B;
116   B.addDereferenceableAttr(b);
117   Call.setAttributes(
118     Call.getAttributes().addAttributes(Call->getContext(), idx,
119                                        AttributeSet::get(Call->getContext(),
120                                                          idx, B)));
121 }
122
123 extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index,
124                                          uint64_t Val) {
125   Function *A = unwrap<Function>(Fn);
126   AttrBuilder B;
127   B.addRawValue(Val);
128   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
129 }
130
131 extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) {
132   Function *A = unwrap<Function>(Fn);
133   AttrBuilder B;
134   B.addDereferenceableAttr(bytes);
135   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
136 }
137
138 extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) {
139   Function *F = unwrap<Function>(Fn);
140   AttrBuilder B;
141   B.addAttribute(Name);
142   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
143 }
144
145 extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
146                                                const char *Name,
147                                                const char *Value) {
148   Function *F = unwrap<Function>(Fn);
149   AttrBuilder B;
150   B.addAttribute(Name, Value);
151   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
152 }
153
154 extern "C" void LLVMRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, uint64_t Val) {
155   Function *A = unwrap<Function>(Fn);
156   const AttributeSet PAL = A->getAttributes();
157   AttrBuilder B(Val);
158   const AttributeSet PALnew =
159     PAL.removeAttributes(A->getContext(), index,
160                          AttributeSet::get(A->getContext(), index, B));
161   A->setAttributes(PALnew);
162 }
163
164 extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
165   Function *f = unwrap<Function>(fn);
166   LLVMContext &C = f->getContext();
167   AttrBuilder B;
168   B.addAttribute(Name);
169   AttributeSet to_remove = AttributeSet::get(C, index, B);
170
171   AttributeSet attrs = f->getAttributes();
172   f->setAttributes(attrs.removeAttributes(f->getContext(),
173                                           index,
174                                           to_remove));
175 }
176
177 // enable fpmath flag UnsafeAlgebra
178 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
179     if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
180         I->setHasUnsafeAlgebra(true);
181     }
182 }
183
184 extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
185                                             LLVMValueRef source,
186                                             const char* Name,
187                                             AtomicOrdering order,
188                                             unsigned alignment) {
189     LoadInst* li = new LoadInst(unwrap(source),0);
190     li->setAtomic(order);
191     li->setAlignment(alignment);
192     return wrap(unwrap(B)->Insert(li, Name));
193 }
194
195 extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
196                                              LLVMValueRef val,
197                                              LLVMValueRef target,
198                                              AtomicOrdering order,
199                                              unsigned alignment) {
200     StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
201     si->setAtomic(order);
202     si->setAlignment(alignment);
203     return wrap(unwrap(B)->Insert(si));
204 }
205
206 extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
207                                                LLVMValueRef target,
208                                                LLVMValueRef old,
209                                                LLVMValueRef source,
210                                                AtomicOrdering order,
211                                                AtomicOrdering failure_order,
212                                                LLVMBool weak) {
213     AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(unwrap(target),
214                                                              unwrap(old),
215                                                              unwrap(source),
216                                                              order,
217                                                              failure_order);
218     acxi->setWeak(weak);
219     return wrap(acxi);
220 }
221 extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
222                                              AtomicOrdering order,
223                                              SynchronizationScope scope) {
224     return wrap(unwrap(B)->CreateFence(order, scope));
225 }
226
227 extern "C" void LLVMSetDebug(int Enabled) {
228 #ifndef NDEBUG
229   DebugFlag = Enabled;
230 #endif
231 }
232
233 extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
234                                       char *AsmString,
235                                       char *Constraints,
236                                       LLVMBool HasSideEffects,
237                                       LLVMBool IsAlignStack,
238                                       unsigned Dialect) {
239     return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
240                                Constraints, HasSideEffects,
241                                IsAlignStack, (InlineAsm::AsmDialect) Dialect));
242 }
243
244 typedef DIBuilder* DIBuilderRef;
245
246 typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
247
248 namespace llvm {
249 DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
250
251 inline Metadata **unwrap(LLVMMetadataRef *Vals) {
252   return reinterpret_cast<Metadata**>(Vals);
253 }
254 }
255
256 template<typename DIT>
257 DIT* unwrapDIptr(LLVMMetadataRef ref) {
258     return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
259 }
260
261 #define DIDescriptor DIScope
262 #define DIArray DINodeArray
263 #define unwrapDI unwrapDIptr
264
265 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
266     return DEBUG_METADATA_VERSION;
267 }
268
269 extern "C" uint32_t LLVMVersionMinor() {
270   return LLVM_VERSION_MINOR;
271 }
272
273 extern "C" uint32_t LLVMVersionMajor() {
274   return LLVM_VERSION_MAJOR;
275 }
276
277 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
278                                       const char *name,
279                                       uint32_t value) {
280     unwrap(M)->addModuleFlag(Module::Warning, name, value);
281 }
282
283 extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
284     return new DIBuilder(*unwrap(M));
285 }
286
287 extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
288     delete Builder;
289 }
290
291 extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
292     Builder->finalize();
293 }
294
295 extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
296     DIBuilderRef Builder,
297     unsigned Lang,
298     const char* File,
299     const char* Dir,
300     const char* Producer,
301     bool isOptimized,
302     const char* Flags,
303     unsigned RuntimeVer,
304     const char* SplitName) {
305     return wrap(Builder->createCompileUnit(Lang,
306                                            File,
307                                            Dir,
308                                            Producer,
309                                            isOptimized,
310                                            Flags,
311                                            RuntimeVer,
312                                            SplitName));
313 }
314
315 extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile(
316     DIBuilderRef Builder,
317     const char* Filename,
318     const char* Directory) {
319     return wrap(Builder->createFile(Filename, Directory));
320 }
321
322 extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
323     DIBuilderRef Builder,
324     LLVMMetadataRef File,
325     LLVMMetadataRef ParameterTypes) {
326     return wrap(Builder->createSubroutineType(
327 #if LLVM_VERSION_MINOR == 7
328         unwrapDI<DIFile>(File),
329 #endif
330         DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
331 }
332
333 extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
334     DIBuilderRef Builder,
335     LLVMMetadataRef Scope,
336     const char* Name,
337     const char* LinkageName,
338     LLVMMetadataRef File,
339     unsigned LineNo,
340     LLVMMetadataRef Ty,
341     bool isLocalToUnit,
342     bool isDefinition,
343     unsigned ScopeLine,
344     unsigned Flags,
345     bool isOptimized,
346     LLVMValueRef Fn,
347     LLVMMetadataRef TParam,
348     LLVMMetadataRef Decl) {
349 #if LLVM_VERSION_MINOR >= 8
350     DITemplateParameterArray TParams =
351         DITemplateParameterArray(unwrap<MDTuple>(TParam));
352     DISubprogram *Sub = Builder->createFunction(
353         unwrapDI<DIScope>(Scope), Name, LinkageName,
354         unwrapDI<DIFile>(File), LineNo,
355         unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
356         Flags, isOptimized,
357         TParams,
358         unwrapDIptr<DISubprogram>(Decl));
359     unwrap<Function>(Fn)->setSubprogram(Sub);
360     return wrap(Sub);
361 #else
362     return wrap(Builder->createFunction(
363         unwrapDI<DIScope>(Scope), Name, LinkageName,
364         unwrapDI<DIFile>(File), LineNo,
365         unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
366         Flags, isOptimized,
367         unwrap<Function>(Fn),
368         unwrapDIptr<MDNode>(TParam),
369         unwrapDIptr<MDNode>(Decl)));
370 #endif
371 }
372
373 extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
374     DIBuilderRef Builder,
375     const char* Name,
376     uint64_t SizeInBits,
377     uint64_t AlignInBits,
378     unsigned Encoding) {
379     return wrap(Builder->createBasicType(
380         Name, SizeInBits,
381         AlignInBits, Encoding));
382 }
383
384 extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType(
385     DIBuilderRef Builder,
386     LLVMMetadataRef PointeeTy,
387     uint64_t SizeInBits,
388     uint64_t AlignInBits,
389     const char* Name) {
390     return wrap(Builder->createPointerType(
391         unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
392 }
393
394 extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
395     DIBuilderRef Builder,
396     LLVMMetadataRef Scope,
397     const char* Name,
398     LLVMMetadataRef File,
399     unsigned LineNumber,
400     uint64_t SizeInBits,
401     uint64_t AlignInBits,
402     unsigned Flags,
403     LLVMMetadataRef DerivedFrom,
404     LLVMMetadataRef Elements,
405     unsigned RunTimeLang,
406     LLVMMetadataRef VTableHolder,
407     const char *UniqueId) {
408     return wrap(Builder->createStructType(
409         unwrapDI<DIDescriptor>(Scope),
410         Name,
411         unwrapDI<DIFile>(File),
412         LineNumber,
413         SizeInBits,
414         AlignInBits,
415         Flags,
416         unwrapDI<DIType>(DerivedFrom),
417         DINodeArray(unwrapDI<MDTuple>(Elements)),
418         RunTimeLang,
419         unwrapDI<DIType>(VTableHolder),
420         UniqueId
421         ));
422 }
423
424 extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType(
425     DIBuilderRef Builder,
426     LLVMMetadataRef Scope,
427     const char* Name,
428     LLVMMetadataRef File,
429     unsigned LineNo,
430     uint64_t SizeInBits,
431     uint64_t AlignInBits,
432     uint64_t OffsetInBits,
433     unsigned Flags,
434     LLVMMetadataRef Ty) {
435     return wrap(Builder->createMemberType(
436         unwrapDI<DIDescriptor>(Scope), Name,
437         unwrapDI<DIFile>(File), LineNo,
438         SizeInBits, AlignInBits, OffsetInBits, Flags,
439         unwrapDI<DIType>(Ty)));
440 }
441
442 extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
443     DIBuilderRef Builder,
444     LLVMMetadataRef Scope,
445     LLVMMetadataRef File,
446     unsigned Line,
447     unsigned Col) {
448     return wrap(Builder->createLexicalBlock(
449         unwrapDI<DIDescriptor>(Scope),
450         unwrapDI<DIFile>(File), Line, Col
451         ));
452 }
453
454 extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
455     DIBuilderRef Builder,
456     LLVMMetadataRef Context,
457     const char* Name,
458     const char* LinkageName,
459     LLVMMetadataRef File,
460     unsigned LineNo,
461     LLVMMetadataRef Ty,
462     bool isLocalToUnit,
463     LLVMValueRef Val,
464     LLVMMetadataRef Decl = NULL) {
465     return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
466         Name,
467         LinkageName,
468         unwrapDI<DIFile>(File),
469         LineNo,
470         unwrapDI<DIType>(Ty),
471         isLocalToUnit,
472         cast<Constant>(unwrap(Val)),
473         unwrapDIptr<MDNode>(Decl)));
474 }
475
476 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
477     DIBuilderRef Builder,
478     unsigned Tag,
479     LLVMMetadataRef Scope,
480     const char* Name,
481     LLVMMetadataRef File,
482     unsigned LineNo,
483     LLVMMetadataRef Ty,
484     bool AlwaysPreserve,
485     unsigned Flags,
486     int64_t* AddrOps,
487     unsigned AddrOpsCount,
488     unsigned ArgNo) {
489 #if LLVM_VERSION_MINOR >= 8
490     if (Tag == 0x100) { // DW_TAG_auto_variable
491         return wrap(Builder->createAutoVariable(
492             unwrapDI<DIDescriptor>(Scope), Name,
493             unwrapDI<DIFile>(File),
494             LineNo,
495             unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
496     } else {
497         return wrap(Builder->createParameterVariable(
498             unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
499             unwrapDI<DIFile>(File),
500             LineNo,
501             unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
502     }
503 #else
504     return wrap(Builder->createLocalVariable(Tag,
505         unwrapDI<DIDescriptor>(Scope), Name,
506         unwrapDI<DIFile>(File),
507         LineNo,
508         unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
509 #endif
510 }
511
512 extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
513     DIBuilderRef Builder,
514     uint64_t Size,
515     uint64_t AlignInBits,
516     LLVMMetadataRef Ty,
517     LLVMMetadataRef Subscripts) {
518     return wrap(Builder->createArrayType(Size, AlignInBits,
519         unwrapDI<DIType>(Ty),
520         DINodeArray(unwrapDI<MDTuple>(Subscripts))
521     ));
522 }
523
524 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
525     DIBuilderRef Builder,
526     uint64_t Size,
527     uint64_t AlignInBits,
528     LLVMMetadataRef Ty,
529     LLVMMetadataRef Subscripts) {
530     return wrap(Builder->createVectorType(Size, AlignInBits,
531         unwrapDI<DIType>(Ty),
532         DINodeArray(unwrapDI<MDTuple>(Subscripts))
533     ));
534 }
535
536 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
537     DIBuilderRef Builder,
538     int64_t Lo,
539     int64_t Count) {
540     return wrap(Builder->getOrCreateSubrange(Lo, Count));
541 }
542
543 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
544     DIBuilderRef Builder,
545     LLVMMetadataRef* Ptr,
546     unsigned Count) {
547     Metadata **DataValue = unwrap(Ptr);
548     return wrap(Builder->getOrCreateArray(
549         ArrayRef<Metadata*>(DataValue, Count)).get());
550 }
551
552 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
553     DIBuilderRef Builder,
554     LLVMValueRef Val,
555     LLVMMetadataRef VarInfo,
556     int64_t* AddrOps,
557     unsigned AddrOpsCount,
558     LLVMValueRef DL,
559     LLVMBasicBlockRef InsertAtEnd) {
560     return wrap(Builder->insertDeclare(
561         unwrap(Val),
562         unwrap<DILocalVariable>(VarInfo),
563         Builder->createExpression(
564           llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
565         DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
566         unwrap(InsertAtEnd)));
567 }
568
569 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
570     DIBuilderRef Builder,
571     LLVMValueRef Val,
572     LLVMMetadataRef VarInfo,
573     int64_t* AddrOps,
574     unsigned AddrOpsCount,
575     LLVMValueRef DL,
576     LLVMValueRef InsertBefore) {
577     return wrap(Builder->insertDeclare(
578         unwrap(Val),
579         unwrap<DILocalVariable>(VarInfo),
580         Builder->createExpression(
581           llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
582         DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
583         unwrap<Instruction>(InsertBefore)));
584 }
585
586 extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator(
587     DIBuilderRef Builder,
588     const char* Name,
589     uint64_t Val)
590 {
591     return wrap(Builder->createEnumerator(Name, Val));
592 }
593
594 extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
595     DIBuilderRef Builder,
596     LLVMMetadataRef Scope,
597     const char* Name,
598     LLVMMetadataRef File,
599     unsigned LineNumber,
600     uint64_t SizeInBits,
601     uint64_t AlignInBits,
602     LLVMMetadataRef Elements,
603     LLVMMetadataRef ClassType)
604 {
605     return wrap(Builder->createEnumerationType(
606         unwrapDI<DIDescriptor>(Scope),
607         Name,
608         unwrapDI<DIFile>(File),
609         LineNumber,
610         SizeInBits,
611         AlignInBits,
612         DINodeArray(unwrapDI<MDTuple>(Elements)),
613         unwrapDI<DIType>(ClassType)));
614 }
615
616 extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
617     DIBuilderRef Builder,
618     LLVMMetadataRef Scope,
619     const char* Name,
620     LLVMMetadataRef File,
621     unsigned LineNumber,
622     uint64_t SizeInBits,
623     uint64_t AlignInBits,
624     unsigned Flags,
625     LLVMMetadataRef Elements,
626     unsigned RunTimeLang,
627     const char* UniqueId)
628 {
629     return wrap(Builder->createUnionType(
630         unwrapDI<DIDescriptor>(Scope),
631         Name,
632         unwrapDI<DIFile>(File),
633         LineNumber,
634         SizeInBits,
635         AlignInBits,
636         Flags,
637         DINodeArray(unwrapDI<MDTuple>(Elements)),
638         RunTimeLang,
639         UniqueId
640         ));
641 }
642
643 extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
644     DIBuilderRef Builder,
645     LLVMMetadataRef Scope,
646     const char* Name,
647     LLVMMetadataRef Ty,
648     LLVMMetadataRef File,
649     unsigned LineNo,
650     unsigned ColumnNo)
651 {
652     return wrap(Builder->createTemplateTypeParameter(
653       unwrapDI<DIDescriptor>(Scope),
654       Name,
655       unwrapDI<DIType>(Ty)
656       ));
657 }
658
659 extern "C" int64_t LLVMDIBuilderCreateOpDeref()
660 {
661     return dwarf::DW_OP_deref;
662 }
663
664 extern "C" int64_t LLVMDIBuilderCreateOpPlus()
665 {
666     return dwarf::DW_OP_plus;
667 }
668
669 extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace(
670     DIBuilderRef Builder,
671     LLVMMetadataRef Scope,
672     const char* Name,
673     LLVMMetadataRef File,
674     unsigned LineNo)
675 {
676     return wrap(Builder->createNameSpace(
677         unwrapDI<DIDescriptor>(Scope),
678         Name,
679         unwrapDI<DIFile>(File),
680         LineNo));
681 }
682
683 extern "C" void LLVMDICompositeTypeSetTypeArray(
684     DIBuilderRef Builder,
685     LLVMMetadataRef CompositeType,
686     LLVMMetadataRef TypeArray)
687 {
688     DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
689     Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
690 }
691
692 extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
693   LLVMContextRef Context,
694   unsigned Line,
695   unsigned Column,
696   LLVMMetadataRef Scope,
697   LLVMMetadataRef InlinedAt) {
698
699     LLVMContext& context = *unwrap(Context);
700
701     DebugLoc debug_loc = DebugLoc::get(Line,
702                                        Column,
703                                        unwrapDIptr<MDNode>(Scope),
704                                        unwrapDIptr<MDNode>(InlinedAt));
705
706     return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode()));
707 }
708
709 extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
710     raw_rust_string_ostream os(str);
711     unwrap<llvm::Type>(Type)->print(os);
712 }
713
714 extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
715     raw_rust_string_ostream os(str);
716     os << "(";
717     unwrap<llvm::Value>(Value)->getType()->print(os);
718     os << ":";
719     unwrap<llvm::Value>(Value)->print(os);
720     os << ")";
721 }
722
723 extern "C" bool
724 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
725     Module *Dst = unwrap(dst);
726     std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
727     ErrorOr<std::unique_ptr<Module>> Src =
728         llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
729     if (!Src) {
730         LLVMRustSetLastError(Src.getError().message().c_str());
731         return false;
732     }
733
734     std::string Err;
735
736     raw_string_ostream Stream(Err);
737     DiagnosticPrinterRawOStream DP(Stream);
738 #if LLVM_VERSION_MINOR >= 8
739     if (Linker::linkModules(*Dst, std::move(Src.get()))) {
740 #else
741     if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
742 #endif
743         LLVMRustSetLastError(Err.c_str());
744         return false;
745     }
746     return true;
747 }
748
749 extern "C" void
750 LLVMRustSetDLLStorageClass(LLVMValueRef Value,
751                            GlobalValue::DLLStorageClassTypes Class) {
752     GlobalValue *V = unwrap<GlobalValue>(Value);
753     V->setDLLStorageClass(Class);
754 }
755
756 // Note that the two following functions look quite similar to the
757 // LLVMGetSectionName function. Sadly, it appears that this function only
758 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
759 // function provided by LLVM doesn't return the length, so we've created our own
760 // function which returns the length as well as the data pointer.
761 //
762 // For an example of this not returning a null terminated string, see
763 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
764 // branches explicitly creates a StringRef without a null terminator, and then
765 // that's returned.
766
767 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
768     return reinterpret_cast<section_iterator*>(SI);
769 }
770
771 extern "C" int
772 LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
773     StringRef ret;
774     if (std::error_code ec = (*unwrap(SI))->getName(ret))
775       report_fatal_error(ec.message());
776     *ptr = ret.data();
777     return ret.size();
778 }
779
780 // LLVMArrayType function does not support 64-bit ElementCount
781 extern "C" LLVMTypeRef
782 LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
783     return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
784 }
785
786 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
787 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
788
789 extern "C" void
790 LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
791     raw_rust_string_ostream os(str);
792     unwrap(T)->print(os);
793 }
794
795 extern "C" void
796 LLVMUnpackOptimizationDiagnostic(
797     LLVMDiagnosticInfoRef di,
798     const char **pass_name_out,
799     LLVMValueRef *function_out,
800     LLVMDebugLocRef *debugloc_out,
801     LLVMTwineRef *message_out)
802 {
803     // Undefined to call this not on an optimization diagnostic!
804     llvm::DiagnosticInfoOptimizationBase *opt
805         = static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
806
807     *pass_name_out = opt->getPassName();
808     *function_out = wrap(&opt->getFunction());
809     *debugloc_out = wrap(&opt->getDebugLoc());
810     *message_out = wrap(&opt->getMsg());
811 }
812
813 extern "C" void
814 LLVMUnpackInlineAsmDiagnostic(
815     LLVMDiagnosticInfoRef di,
816     unsigned *cookie_out,
817     LLVMTwineRef *message_out,
818     LLVMValueRef *instruction_out)
819 {
820     // Undefined to call this not on an inline assembly diagnostic!
821     llvm::DiagnosticInfoInlineAsm *ia
822         = static_cast<llvm::DiagnosticInfoInlineAsm*>(unwrap(di));
823
824     *cookie_out = ia->getLocCookie();
825     *message_out = wrap(&ia->getMsgStr());
826     *instruction_out = wrap(ia->getInstruction());
827 }
828
829 extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
830     raw_rust_string_ostream os(str);
831     DiagnosticPrinterRawOStream dp(os);
832     unwrap(di)->print(dp);
833 }
834
835 extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
836     return unwrap(di)->getKind();
837 }
838
839 extern "C" void LLVMWriteDebugLocToString(
840     LLVMContextRef C,
841     LLVMDebugLocRef dl,
842     RustStringRef str)
843 {
844     raw_rust_string_ostream os(str);
845     unwrap(dl)->print(os);
846 }
847
848 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
849
850 extern "C" void LLVMSetInlineAsmDiagnosticHandler(
851     LLVMContextRef C,
852     LLVMContext::InlineAsmDiagHandlerTy H,
853     void *CX)
854 {
855     unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
856 }
857
858 extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
859     raw_rust_string_ostream os(str);
860     unwrap(d)->print("", os);
861 }
862
863 extern "C" LLVMValueRef
864 LLVMRustBuildLandingPad(LLVMBuilderRef Builder,
865                         LLVMTypeRef Ty,
866                         LLVMValueRef PersFn,
867                         unsigned NumClauses,
868                         const char* Name,
869                         LLVMValueRef F) {
870     return LLVMBuildLandingPad(Builder, Ty, PersFn, NumClauses, Name);
871 }
872
873 extern "C" LLVMValueRef
874 LLVMRustBuildCleanupPad(LLVMBuilderRef Builder,
875                         LLVMValueRef ParentPad,
876                         unsigned ArgCnt,
877                         LLVMValueRef *LLArgs,
878                         const char *Name) {
879 #if LLVM_VERSION_MINOR >= 8
880     Value **Args = unwrap(LLArgs);
881     if (ParentPad == NULL) {
882         Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
883         ParentPad = wrap(Constant::getNullValue(Ty));
884     }
885     return wrap(unwrap(Builder)->CreateCleanupPad(unwrap(ParentPad),
886                                                   ArrayRef<Value*>(Args, ArgCnt),
887                                                   Name));
888 #else
889     return NULL;
890 #endif
891 }
892
893 extern "C" LLVMValueRef
894 LLVMRustBuildCleanupRet(LLVMBuilderRef Builder,
895                         LLVMValueRef CleanupPad,
896                         LLVMBasicBlockRef UnwindBB) {
897 #if LLVM_VERSION_MINOR >= 8
898     CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
899     return wrap(unwrap(Builder)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
900 #else
901     return NULL;
902 #endif
903 }
904
905 extern "C" LLVMValueRef
906 LLVMRustBuildCatchPad(LLVMBuilderRef Builder,
907                       LLVMValueRef ParentPad,
908                       unsigned ArgCnt,
909                       LLVMValueRef *LLArgs,
910                       const char *Name) {
911 #if LLVM_VERSION_MINOR >= 8
912     Value **Args = unwrap(LLArgs);
913     return wrap(unwrap(Builder)->CreateCatchPad(unwrap(ParentPad),
914                                                 ArrayRef<Value*>(Args, ArgCnt),
915                                                 Name));
916 #else
917     return NULL;
918 #endif
919 }
920
921 extern "C" LLVMValueRef
922 LLVMRustBuildCatchRet(LLVMBuilderRef Builder,
923                       LLVMValueRef Pad,
924                       LLVMBasicBlockRef BB) {
925 #if LLVM_VERSION_MINOR >= 8
926     return wrap(unwrap(Builder)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
927                                                 unwrap(BB)));
928 #else
929     return NULL;
930 #endif
931 }
932
933 extern "C" LLVMValueRef
934 LLVMRustBuildCatchSwitch(LLVMBuilderRef Builder,
935                          LLVMValueRef ParentPad,
936                          LLVMBasicBlockRef BB,
937                          unsigned NumHandlers,
938                          const char *Name) {
939 #if LLVM_VERSION_MINOR >= 8
940     if (ParentPad == NULL) {
941         Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
942         ParentPad = wrap(Constant::getNullValue(Ty));
943     }
944     return wrap(unwrap(Builder)->CreateCatchSwitch(unwrap(ParentPad),
945                                                    unwrap(BB),
946                                                    NumHandlers,
947                                                    Name));
948 #else
949     return NULL;
950 #endif
951 }
952
953 extern "C" void
954 LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
955                    LLVMBasicBlockRef Handler) {
956 #if LLVM_VERSION_MINOR >= 8
957     Value *CatchSwitch = unwrap(CatchSwitchRef);
958     cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
959 #endif
960 }
961
962 extern "C" void
963 LLVMRustSetPersonalityFn(LLVMBuilderRef B,
964                          LLVMValueRef Personality) {
965 #if LLVM_VERSION_MINOR >= 8
966     unwrap(B)->GetInsertBlock()
967              ->getParent()
968              ->setPersonalityFn(cast<Function>(unwrap(Personality)));
969 #endif
970 }
971
972 #if LLVM_VERSION_MINOR >= 8
973 extern "C" OperandBundleDef*
974 LLVMRustBuildOperandBundleDef(const char *Name,
975                               LLVMValueRef *Inputs,
976                               unsigned NumInputs) {
977   return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
978 }
979
980 extern "C" void
981 LLVMRustFreeOperandBundleDef(OperandBundleDef* Bundle) {
982   delete Bundle;
983 }
984
985 extern "C" LLVMValueRef
986 LLVMRustBuildCall(LLVMBuilderRef B,
987                     LLVMValueRef Fn,
988                     LLVMValueRef *Args,
989                     unsigned NumArgs,
990                     OperandBundleDef *Bundle,
991                     const char *Name) {
992     unsigned len = Bundle ? 1 : 0;
993     ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
994     return wrap(unwrap(B)->CreateCall(unwrap(Fn),
995                                       makeArrayRef(unwrap(Args), NumArgs),
996                                       Bundles,
997                                       Name));
998 }
999
1000 extern "C" LLVMValueRef
1001 LLVMRustBuildInvoke(LLVMBuilderRef B,
1002                     LLVMValueRef Fn,
1003                     LLVMValueRef *Args,
1004                     unsigned NumArgs,
1005                     LLVMBasicBlockRef Then,
1006                     LLVMBasicBlockRef Catch,
1007                     OperandBundleDef *Bundle,
1008                     const char *Name) {
1009     unsigned len = Bundle ? 1 : 0;
1010     ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
1011     return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
1012                                         makeArrayRef(unwrap(Args), NumArgs),
1013                                         Bundles,
1014                                         Name));
1015 }
1016 #else
1017 extern "C" void*
1018 LLVMRustBuildOperandBundleDef(const char *Name,
1019                               LLVMValueRef *Inputs,
1020                               unsigned NumInputs) {
1021   return NULL;
1022 }
1023
1024 extern "C" void
1025 LLVMRustFreeOperandBundleDef(void* Bundle) {
1026 }
1027
1028 extern "C" LLVMValueRef
1029 LLVMRustBuildCall(LLVMBuilderRef B,
1030                     LLVMValueRef Fn,
1031                     LLVMValueRef *Args,
1032                     unsigned NumArgs,
1033                     void *Bundle,
1034                     const char *Name) {
1035     return LLVMBuildCall(B, Fn, Args, NumArgs, Name);
1036 }
1037
1038 extern "C" LLVMValueRef
1039 LLVMRustBuildInvoke(LLVMBuilderRef B,
1040                     LLVMValueRef Fn,
1041                     LLVMValueRef *Args,
1042                     unsigned NumArgs,
1043                     LLVMBasicBlockRef Then,
1044                     LLVMBasicBlockRef Catch,
1045                     void *Bundle,
1046                     const char *Name) {
1047     return LLVMBuildInvoke(B, Fn, Args, NumArgs, Then, Catch, Name);
1048 }
1049 #endif
1050
1051 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) {
1052     auto point = unwrap(BB)->getFirstInsertionPt();
1053     unwrap(B)->SetInsertPoint(unwrap(BB), point);
1054 }
1055
1056 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, const char *Name) {
1057     Triple TargetTriple(unwrap(M)->getTargetTriple());
1058     GlobalObject *GV = unwrap<GlobalObject>(V);
1059     if (!TargetTriple.isOSBinFormatMachO()) {
1060         GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
1061     }
1062 }
1063
1064 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
1065     GlobalObject *GV = unwrap<GlobalObject>(V);
1066     GV->setComdat(nullptr);
1067 }