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