]> git.lizzy.rs Git - rust.git/blob - src/rustllvm/RustWrapper.cpp
Remove useless `const`
[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, uint64_t Val) {
124   Function *A = unwrap<Function>(Fn);
125   AttrBuilder B;
126   B.addRawValue(Val);
127   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
128 }
129
130 extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) {
131   Function *A = unwrap<Function>(Fn);
132   AttrBuilder B;
133   B.addDereferenceableAttr(bytes);
134   A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
135 }
136
137 extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) {
138   Function *F = unwrap<Function>(Fn);
139   AttrBuilder B;
140   B.addAttribute(Name);
141   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
142 }
143
144 extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
145   Function *f = unwrap<Function>(fn);
146   LLVMContext &C = f->getContext();
147   AttrBuilder B;
148   B.addAttribute(Name);
149   AttributeSet to_remove = AttributeSet::get(C, index, B);
150
151   AttributeSet attrs = f->getAttributes();
152   f->setAttributes(attrs.removeAttributes(f->getContext(),
153                                           index,
154                                           to_remove));
155 }
156
157 extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
158                                             LLVMValueRef source,
159                                             const char* Name,
160                                             AtomicOrdering order,
161                                             unsigned alignment) {
162     LoadInst* li = new LoadInst(unwrap(source),0);
163     li->setVolatile(true);
164     li->setAtomic(order);
165     li->setAlignment(alignment);
166     return wrap(unwrap(B)->Insert(li, Name));
167 }
168
169 extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
170                                              LLVMValueRef val,
171                                              LLVMValueRef target,
172                                              AtomicOrdering order,
173                                              unsigned alignment) {
174     StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
175     si->setVolatile(true);
176     si->setAtomic(order);
177     si->setAlignment(alignment);
178     return wrap(unwrap(B)->Insert(si));
179 }
180
181 extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
182                                                LLVMValueRef target,
183                                                LLVMValueRef old,
184                                                LLVMValueRef source,
185                                                AtomicOrdering order,
186                                                AtomicOrdering failure_order) {
187     return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
188                                                unwrap(source), order,
189                                                failure_order
190                                                ));
191 }
192 extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
193                                              AtomicOrdering order,
194                                              SynchronizationScope scope) {
195     return wrap(unwrap(B)->CreateFence(order, scope));
196 }
197
198 extern "C" void LLVMSetDebug(int Enabled) {
199 #ifndef NDEBUG
200   DebugFlag = Enabled;
201 #endif
202 }
203
204 extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
205                                       char *AsmString,
206                                       char *Constraints,
207                                       LLVMBool HasSideEffects,
208                                       LLVMBool IsAlignStack,
209                                       unsigned Dialect) {
210     return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
211                                Constraints, HasSideEffects,
212                                IsAlignStack, (InlineAsm::AsmDialect) Dialect));
213 }
214
215 typedef DIBuilder* DIBuilderRef;
216
217 #if LLVM_VERSION_MINOR >= 6
218 typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
219
220 namespace llvm {
221 DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
222
223 inline Metadata **unwrap(LLVMMetadataRef *Vals) {
224   return reinterpret_cast<Metadata**>(Vals);
225 }
226 }
227 #else
228 typedef LLVMValueRef LLVMMetadataRef;
229 #endif
230
231 template<typename DIT>
232 DIT unwrapDI(LLVMMetadataRef ref) {
233     return DIT(ref ? unwrap<MDNode>(ref) : NULL);
234 }
235
236 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
237     return DEBUG_METADATA_VERSION;
238 }
239
240 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
241                                       const char *name,
242                                       uint32_t value) {
243     unwrap(M)->addModuleFlag(Module::Warning, name, value);
244 }
245
246 extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
247     return new DIBuilder(*unwrap(M));
248 }
249
250 extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
251     delete Builder;
252 }
253
254 extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
255     Builder->finalize();
256 }
257
258 extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
259     DIBuilderRef Builder,
260     unsigned Lang,
261     const char* File,
262     const char* Dir,
263     const char* Producer,
264     bool isOptimized,
265     const char* Flags,
266     unsigned RuntimeVer,
267     const char* SplitName) {
268     return wrap(Builder->createCompileUnit(Lang,
269                                            File,
270                                            Dir,
271                                            Producer,
272                                            isOptimized,
273                                            Flags,
274                                            RuntimeVer,
275                                            SplitName));
276 }
277
278 extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile(
279     DIBuilderRef Builder,
280     const char* Filename,
281     const char* Directory) {
282     return wrap(Builder->createFile(Filename, Directory));
283 }
284
285 extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
286     DIBuilderRef Builder,
287     LLVMMetadataRef File,
288     LLVMMetadataRef ParameterTypes) {
289     return wrap(Builder->createSubroutineType(
290         unwrapDI<DIFile>(File),
291 #if LLVM_VERSION_MINOR >= 6
292         unwrapDI<DITypeArray>(ParameterTypes)));
293 #else
294         unwrapDI<DIArray>(ParameterTypes)));
295 #endif
296 }
297
298 extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
299     DIBuilderRef Builder,
300     LLVMMetadataRef Scope,
301     const char* Name,
302     const char* LinkageName,
303     LLVMMetadataRef File,
304     unsigned LineNo,
305     LLVMMetadataRef Ty,
306     bool isLocalToUnit,
307     bool isDefinition,
308     unsigned ScopeLine,
309     unsigned Flags,
310     bool isOptimized,
311     LLVMValueRef Fn,
312     LLVMMetadataRef TParam,
313     LLVMMetadataRef Decl) {
314     return wrap(Builder->createFunction(
315         unwrapDI<DIScope>(Scope), Name, LinkageName,
316         unwrapDI<DIFile>(File), LineNo,
317         unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
318         Flags, isOptimized,
319         unwrap<Function>(Fn),
320         unwrapDI<MDNode*>(TParam),
321         unwrapDI<MDNode*>(Decl)));
322 }
323
324 extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
325     DIBuilderRef Builder,
326     const char* Name,
327     uint64_t SizeInBits,
328     uint64_t AlignInBits,
329     unsigned Encoding) {
330     return wrap(Builder->createBasicType(
331         Name, SizeInBits,
332         AlignInBits, Encoding));
333 }
334
335 extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType(
336     DIBuilderRef Builder,
337     LLVMMetadataRef PointeeTy,
338     uint64_t SizeInBits,
339     uint64_t AlignInBits,
340     const char* Name) {
341     return wrap(Builder->createPointerType(
342         unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
343 }
344
345 extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
346     DIBuilderRef Builder,
347     LLVMMetadataRef Scope,
348     const char* Name,
349     LLVMMetadataRef File,
350     unsigned LineNumber,
351     uint64_t SizeInBits,
352     uint64_t AlignInBits,
353     unsigned Flags,
354     LLVMMetadataRef DerivedFrom,
355     LLVMMetadataRef Elements,
356     unsigned RunTimeLang,
357     LLVMMetadataRef VTableHolder,
358     const char *UniqueId) {
359     return wrap(Builder->createStructType(
360         unwrapDI<DIDescriptor>(Scope),
361         Name,
362         unwrapDI<DIFile>(File),
363         LineNumber,
364         SizeInBits,
365         AlignInBits,
366         Flags,
367         unwrapDI<DIType>(DerivedFrom),
368         unwrapDI<DIArray>(Elements),
369         RunTimeLang,
370         unwrapDI<DIType>(VTableHolder),
371         UniqueId
372         ));
373 }
374
375 extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType(
376     DIBuilderRef Builder,
377     LLVMMetadataRef Scope,
378     const char* Name,
379     LLVMMetadataRef File,
380     unsigned LineNo,
381     uint64_t SizeInBits,
382     uint64_t AlignInBits,
383     uint64_t OffsetInBits,
384     unsigned Flags,
385     LLVMMetadataRef Ty) {
386     return wrap(Builder->createMemberType(
387         unwrapDI<DIDescriptor>(Scope), Name,
388         unwrapDI<DIFile>(File), LineNo,
389         SizeInBits, AlignInBits, OffsetInBits, Flags,
390         unwrapDI<DIType>(Ty)));
391 }
392
393 extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
394     DIBuilderRef Builder,
395     LLVMMetadataRef Scope,
396     LLVMMetadataRef File,
397     unsigned Line,
398     unsigned Col) {
399     return wrap(Builder->createLexicalBlock(
400         unwrapDI<DIDescriptor>(Scope),
401         unwrapDI<DIFile>(File), Line, Col
402 #if LLVM_VERSION_MINOR == 5
403         , 0
404 #endif
405         ));
406 }
407
408 extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
409     DIBuilderRef Builder,
410     LLVMMetadataRef Context,
411     const char* Name,
412     const char* LinkageName,
413     LLVMMetadataRef File,
414     unsigned LineNo,
415     LLVMMetadataRef Ty,
416     bool isLocalToUnit,
417     LLVMValueRef Val,
418     LLVMMetadataRef Decl = NULL) {
419 #if LLVM_VERSION_MINOR >= 6
420     return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
421 #else
422     return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
423 #endif
424         Name,
425         LinkageName,
426         unwrapDI<DIFile>(File),
427         LineNo,
428         unwrapDI<DIType>(Ty),
429         isLocalToUnit,
430         cast<Constant>(unwrap(Val)),
431         unwrapDI<MDNode*>(Decl)));
432 }
433
434 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
435     DIBuilderRef Builder,
436     unsigned Tag,
437     LLVMMetadataRef Scope,
438     const char* Name,
439     LLVMMetadataRef File,
440     unsigned LineNo,
441     LLVMMetadataRef Ty,
442     bool AlwaysPreserve,
443     unsigned Flags,
444     int64_t* AddrOps,
445     unsigned AddrOpsCount,
446     unsigned ArgNo) {
447 #if LLVM_VERSION_MINOR == 5
448     if (AddrOpsCount > 0) {
449         SmallVector<llvm::Value *, 16> addr_ops;
450         llvm::Type *Int64Ty = Type::getInt64Ty(unwrap<MDNode>(Scope)->getContext());
451         for (unsigned i = 0; i < AddrOpsCount; ++i)
452             addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i]));
453
454         return wrap(Builder->createComplexVariable(
455             Tag,
456             unwrapDI<DIDescriptor>(Scope),
457             Name,
458             unwrapDI<DIFile>(File),
459             LineNo,
460             unwrapDI<DIType>(Ty),
461             addr_ops,
462             ArgNo
463         ));
464     }
465 #endif
466     return wrap(Builder->createLocalVariable(Tag,
467         unwrapDI<DIDescriptor>(Scope), Name,
468         unwrapDI<DIFile>(File),
469         LineNo,
470         unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
471 }
472
473 extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
474     DIBuilderRef Builder,
475     uint64_t Size,
476     uint64_t AlignInBits,
477     LLVMMetadataRef Ty,
478     LLVMMetadataRef Subscripts) {
479     return wrap(Builder->createArrayType(Size, AlignInBits,
480         unwrapDI<DIType>(Ty),
481         unwrapDI<DIArray>(Subscripts)));
482 }
483
484 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
485     DIBuilderRef Builder,
486     uint64_t Size,
487     uint64_t AlignInBits,
488     LLVMMetadataRef Ty,
489     LLVMMetadataRef Subscripts) {
490     return wrap(Builder->createVectorType(Size, AlignInBits,
491         unwrapDI<DIType>(Ty),
492         unwrapDI<DIArray>(Subscripts)));
493 }
494
495 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
496     DIBuilderRef Builder,
497     int64_t Lo,
498     int64_t Count) {
499     return wrap(Builder->getOrCreateSubrange(Lo, Count));
500 }
501
502 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
503     DIBuilderRef Builder,
504     LLVMMetadataRef* Ptr,
505     unsigned Count) {
506     return wrap(Builder->getOrCreateArray(
507 #if LLVM_VERSION_MINOR >= 6
508         ArrayRef<Metadata*>(unwrap(Ptr), Count)));
509 #else
510         ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
511 #endif
512 }
513
514 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
515     DIBuilderRef Builder,
516     LLVMValueRef Val,
517     LLVMMetadataRef VarInfo,
518     int64_t* AddrOps,
519     unsigned AddrOpsCount,
520     LLVMBasicBlockRef InsertAtEnd) {
521 #if LLVM_VERSION_MINOR >= 6
522     DIExpression Expr;
523     if (AddrOpsCount == 0) {
524       Expr = Builder->createExpression();
525     } else {
526       llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
527       Expr = Builder->createExpression(addr_ops);
528     }
529 #endif
530     return wrap(Builder->insertDeclare(
531         unwrap(Val),
532         unwrapDI<DIVariable>(VarInfo),
533 #if LLVM_VERSION_MINOR >= 6
534         Expr,
535 #endif
536         unwrap(InsertAtEnd)));
537 }
538
539 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
540     DIBuilderRef Builder,
541     LLVMValueRef Val,
542     LLVMMetadataRef VarInfo,
543     int64_t* AddrOps,
544     unsigned AddrOpsCount,
545     LLVMValueRef InsertBefore) {
546 #if LLVM_VERSION_MINOR >= 6
547     DIExpression Expr;
548     if (AddrOpsCount == 0) {
549       Expr = Builder->createExpression();
550     } else {
551       llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
552       Expr = Builder->createExpression(addr_ops);
553     }
554 #endif
555     return wrap(Builder->insertDeclare(
556         unwrap(Val),
557         unwrapDI<DIVariable>(VarInfo),
558 #if LLVM_VERSION_MINOR >= 6
559         Expr,
560 #endif
561         unwrap<Instruction>(InsertBefore)));
562 }
563
564 extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator(
565     DIBuilderRef Builder,
566     const char* Name,
567     uint64_t Val)
568 {
569     return wrap(Builder->createEnumerator(Name, Val));
570 }
571
572 extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
573     DIBuilderRef Builder,
574     LLVMMetadataRef Scope,
575     const char* Name,
576     LLVMMetadataRef File,
577     unsigned LineNumber,
578     uint64_t SizeInBits,
579     uint64_t AlignInBits,
580     LLVMMetadataRef Elements,
581     LLVMMetadataRef ClassType)
582 {
583     return wrap(Builder->createEnumerationType(
584         unwrapDI<DIDescriptor>(Scope),
585         Name,
586         unwrapDI<DIFile>(File),
587         LineNumber,
588         SizeInBits,
589         AlignInBits,
590         unwrapDI<DIArray>(Elements),
591         unwrapDI<DIType>(ClassType)));
592 }
593
594 extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
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     unsigned Flags,
603     LLVMMetadataRef Elements,
604     unsigned RunTimeLang,
605     const char* UniqueId)
606 {
607     return wrap(Builder->createUnionType(
608         unwrapDI<DIDescriptor>(Scope),
609         Name,
610         unwrapDI<DIFile>(File),
611         LineNumber,
612         SizeInBits,
613         AlignInBits,
614         Flags,
615         unwrapDI<DIArray>(Elements),
616         RunTimeLang,
617         UniqueId
618         ));
619 }
620
621 extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
622     DIBuilderRef Builder,
623     LLVMMetadataRef Scope,
624     const char* Name,
625     LLVMMetadataRef Ty,
626     LLVMMetadataRef File,
627     unsigned LineNo,
628     unsigned ColumnNo)
629 {
630     return wrap(Builder->createTemplateTypeParameter(
631       unwrapDI<DIDescriptor>(Scope),
632       Name,
633       unwrapDI<DIType>(Ty),
634       unwrapDI<MDNode*>(File),
635       LineNo,
636       ColumnNo));
637 }
638
639 extern "C" int64_t LLVMDIBuilderCreateOpDeref()
640 {
641     return dwarf::DW_OP_deref;
642 }
643
644 extern "C" int64_t LLVMDIBuilderCreateOpPlus()
645 {
646     return dwarf::DW_OP_plus;
647 }
648
649 extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace(
650     DIBuilderRef Builder,
651     LLVMMetadataRef Scope,
652     const char* Name,
653     LLVMMetadataRef File,
654     unsigned LineNo)
655 {
656     return wrap(Builder->createNameSpace(
657         unwrapDI<DIDescriptor>(Scope),
658         Name,
659         unwrapDI<DIFile>(File),
660         LineNo));
661 }
662
663 extern "C" void LLVMDICompositeTypeSetTypeArray(
664     DIBuilderRef Builder,
665     LLVMMetadataRef CompositeType,
666     LLVMMetadataRef TypeArray)
667 {
668 #if LLVM_VERSION_MINOR >= 6
669     DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
670     Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
671 #else
672     unwrapDI<DICompositeType>(CompositeType).setTypeArray(unwrapDI<DIArray>(TypeArray));
673 #endif
674 }
675
676 extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
677   LLVMContextRef Context,
678   unsigned Line,
679   unsigned Column,
680   LLVMMetadataRef Scope,
681   LLVMMetadataRef InlinedAt) {
682
683     LLVMContext& context = *unwrap(Context);
684
685     DebugLoc debug_loc = DebugLoc::get(Line,
686                                        Column,
687                                        unwrapDI<MDNode*>(Scope),
688                                        unwrapDI<MDNode*>(InlinedAt));
689
690 #if LLVM_VERSION_MINOR >= 6
691     return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
692 #else
693     return wrap(debug_loc.getAsMDNode(context));
694 #endif
695 }
696
697 extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
698     raw_rust_string_ostream os(str);
699     unwrap<llvm::Type>(Type)->print(os);
700 }
701
702 extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
703     raw_rust_string_ostream os(str);
704     os << "(";
705     unwrap<llvm::Value>(Value)->getType()->print(os);
706     os << ":";
707     unwrap<llvm::Value>(Value)->print(os);
708     os << ")";
709 }
710
711 extern "C" bool
712 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
713     Module *Dst = unwrap(dst);
714 #if LLVM_VERSION_MINOR >= 6
715     std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
716     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
717 #else
718     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
719     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
720 #endif
721     if (!Src) {
722         LLVMRustSetLastError(Src.getError().message().c_str());
723 #if LLVM_VERSION_MINOR == 5
724         delete buf;
725 #endif
726         return false;
727     }
728
729     std::string Err;
730
731 #if LLVM_VERSION_MINOR >= 6
732     raw_string_ostream Stream(Err);
733     DiagnosticPrinterRawOStream DP(Stream);
734     if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
735 #else
736     if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
737 #endif
738         LLVMRustSetLastError(Err.c_str());
739         return false;
740     }
741     return true;
742 }
743
744 extern "C" void*
745 LLVMRustOpenArchive(char *path) {
746     ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
747                                                                           -1,
748                                                                           false);
749     if (!buf_or) {
750         LLVMRustSetLastError(buf_or.getError().message().c_str());
751         return nullptr;
752     }
753
754 #if LLVM_VERSION_MINOR >= 6
755     ErrorOr<std::unique_ptr<Archive>> archive_or =
756         Archive::create(buf_or.get()->getMemBufferRef());
757
758     if (!archive_or) {
759         LLVMRustSetLastError(archive_or.getError().message().c_str());
760         return nullptr;
761     }
762
763     OwningBinary<Archive> *ret = new OwningBinary<Archive>(
764             std::move(archive_or.get()), std::move(buf_or.get()));
765 #else
766     std::error_code err;
767     Archive *ret = new Archive(std::move(buf_or.get()), err);
768     if (err) {
769         LLVMRustSetLastError(err.message().c_str());
770         return nullptr;
771     }
772 #endif
773
774     return ret;
775 }
776
777 #if LLVM_VERSION_MINOR >= 6
778 typedef OwningBinary<Archive> RustArchive;
779 #define GET_ARCHIVE(a) ((a)->getBinary())
780 #else
781 typedef Archive RustArchive;
782 #define GET_ARCHIVE(a) (a)
783 #endif
784
785 extern "C" void
786 LLVMRustDestroyArchive(RustArchive *ar) {
787     delete ar;
788 }
789
790 struct RustArchiveIterator {
791     Archive::child_iterator cur;
792     Archive::child_iterator end;
793 };
794
795 extern "C" RustArchiveIterator*
796 LLVMRustArchiveIteratorNew(RustArchive *ra) {
797     Archive *ar = GET_ARCHIVE(ra);
798     RustArchiveIterator *rai = new RustArchiveIterator();
799     rai->cur = ar->child_begin();
800     rai->end = ar->child_end();
801     return rai;
802 }
803
804 extern "C" const Archive::Child*
805 LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
806     if (rai->cur == rai->end)
807         return NULL;
808     const Archive::Child &ret = *rai->cur;
809     return &ret;
810 }
811
812 extern "C" void
813 LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
814     if (rai->cur == rai->end)
815         return;
816     ++rai->cur;
817 }
818
819 extern "C" void
820 LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
821     delete rai;
822 }
823
824 extern "C" const char*
825 LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
826     ErrorOr<StringRef> name_or_err = child->getName();
827     if (name_or_err.getError())
828         return NULL;
829     StringRef name = name_or_err.get();
830     *size = name.size();
831     return name.data();
832 }
833
834 extern "C" const char*
835 LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
836     StringRef buf = child->getBuffer();
837     *size = buf.size();
838     return buf.data();
839 }
840
841 extern "C" void
842 LLVMRustSetDLLStorageClass(LLVMValueRef Value,
843                            GlobalValue::DLLStorageClassTypes Class) {
844     GlobalValue *V = unwrap<GlobalValue>(Value);
845     V->setDLLStorageClass(Class);
846 }
847
848 // Note that the two following functions look quite similar to the
849 // LLVMGetSectionName function. Sadly, it appears that this function only
850 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
851 // function provided by LLVM doesn't return the length, so we've created our own
852 // function which returns the length as well as the data pointer.
853 //
854 // For an example of this not returning a null terminated string, see
855 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
856 // branches explicitly creates a StringRef without a null terminator, and then
857 // that's returned.
858
859 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
860     return reinterpret_cast<section_iterator*>(SI);
861 }
862
863 extern "C" int
864 LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
865     StringRef ret;
866     if (std::error_code ec = (*unwrap(SI))->getName(ret))
867       report_fatal_error(ec.message());
868     *ptr = ret.data();
869     return ret.size();
870 }
871
872 // LLVMArrayType function does not support 64-bit ElementCount
873 extern "C" LLVMTypeRef
874 LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
875     return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
876 }
877
878 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
879 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
880
881 extern "C" void
882 LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
883     raw_rust_string_ostream os(str);
884     unwrap(T)->print(os);
885 }
886
887 extern "C" void
888 LLVMUnpackOptimizationDiagnostic(
889     LLVMDiagnosticInfoRef di,
890     const char **pass_name_out,
891     LLVMValueRef *function_out,
892     LLVMDebugLocRef *debugloc_out,
893     LLVMTwineRef *message_out)
894 {
895     // Undefined to call this not on an optimization diagnostic!
896     llvm::DiagnosticInfoOptimizationBase *opt
897         = static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
898
899     *pass_name_out = opt->getPassName();
900     *function_out = wrap(&opt->getFunction());
901     *debugloc_out = wrap(&opt->getDebugLoc());
902     *message_out = wrap(&opt->getMsg());
903 }
904
905 extern "C" void
906 LLVMUnpackInlineAsmDiagnostic(
907     LLVMDiagnosticInfoRef di,
908     unsigned *cookie_out,
909     LLVMTwineRef *message_out,
910     LLVMValueRef *instruction_out)
911 {
912     // Undefined to call this not on an inline assembly diagnostic!
913     llvm::DiagnosticInfoInlineAsm *ia
914         = static_cast<llvm::DiagnosticInfoInlineAsm*>(unwrap(di));
915
916     *cookie_out = ia->getLocCookie();
917     *message_out = wrap(&ia->getMsgStr());
918     *instruction_out = wrap(ia->getInstruction());
919 }
920
921 extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
922     raw_rust_string_ostream os(str);
923     DiagnosticPrinterRawOStream dp(os);
924     unwrap(di)->print(dp);
925 }
926
927 extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
928     return unwrap(di)->getKind();
929 }
930
931 extern "C" void LLVMWriteDebugLocToString(
932     LLVMContextRef C,
933     LLVMDebugLocRef dl,
934     RustStringRef str)
935 {
936     raw_rust_string_ostream os(str);
937     unwrap(dl)->print(*unwrap(C), os);
938 }
939
940 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
941
942 extern "C" void LLVMSetInlineAsmDiagnosticHandler(
943     LLVMContextRef C,
944     LLVMContext::InlineAsmDiagHandlerTy H,
945     void *CX)
946 {
947     unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
948 }
949
950 extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
951     raw_rust_string_ostream os(str);
952     unwrap(d)->print("", os);
953 }