]> git.lizzy.rs Git - rust.git/blob - src/rustllvm/RustWrapper.cpp
auto merge of #13711 : alexcrichton/rust/snapshots, r=brson
[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
15 //===----------------------------------------------------------------------===
16 //
17 // This file defines alternate interfaces to core functions that are more
18 // readily callable by Rust's FFI.
19 //
20 //===----------------------------------------------------------------------===
21
22 using namespace llvm;
23 using namespace llvm::sys;
24 using namespace llvm::object;
25
26 static char *LastError;
27
28 extern "C" LLVMMemoryBufferRef
29 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
30   LLVMMemoryBufferRef MemBuf = NULL;
31   char *err = NULL;
32   LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, &err);
33   if (err != NULL) {
34     LLVMRustSetLastError(err);
35   }
36   return MemBuf;
37 }
38
39 extern "C" char *LLVMRustGetLastError(void) {
40   char *ret = LastError;
41   LastError = NULL;
42   return ret;
43 }
44
45 void LLVMRustSetLastError(const char *err) {
46   free((void*) LastError);
47   LastError = strdup(err);
48 }
49
50 extern "C" void
51 LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) {
52     unwrap(M)->setTargetTriple(Triple::normalize(triple));
53 }
54
55 extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
56                                               LLVMBool SignExtend) {
57   return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
58 }
59
60 extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy,
61            unsigned N_hi,
62            unsigned N_lo,
63            LLVMBool SignExtend) {
64   unsigned long long N = N_hi;
65   N <<= 32;
66   N |= N_lo;
67   return LLVMConstInt(IntTy, N, SignExtend);
68 }
69
70 extern "C" void LLVMRustPrintPassTimings() {
71   raw_fd_ostream OS (2, false); // stderr.
72   TimerGroup::printAll(OS);
73 }
74
75 extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
76                                                 const char* Name,
77                                                 LLVMTypeRef FunctionTy) {
78   return wrap(unwrap(M)->getOrInsertFunction(Name,
79                                              unwrap<FunctionType>(FunctionTy)));
80 }
81
82 extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
83   return wrap(Type::getMetadataTy(*unwrap(C)));
84 }
85
86 extern "C" void LLVMAddFunctionAttrString(LLVMValueRef fn, const char *Name) {
87   unwrap<Function>(fn)->addFnAttr(Name);
88 }
89
90 extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, const char *Name) {
91   Function *f = unwrap<Function>(fn);
92   LLVMContext &C = f->getContext();
93   AttrBuilder B;
94   B.addAttribute(Name);
95   AttributeSet to_remove = AttributeSet::get(C, AttributeSet::FunctionIndex, B);
96
97   AttributeSet attrs = f->getAttributes();
98   f->setAttributes(attrs.removeAttributes(f->getContext(),
99                                           AttributeSet::FunctionIndex,
100                                           to_remove));
101 }
102
103 extern "C" void LLVMAddReturnAttribute(LLVMValueRef Fn, LLVMAttribute PA) {
104   Function *A = unwrap<Function>(Fn);
105   AttrBuilder B(PA);
106   A->addAttributes(AttributeSet::ReturnIndex,
107                    AttributeSet::get(A->getContext(), AttributeSet::ReturnIndex,  B));
108 }
109
110 extern "C" void LLVMRemoveReturnAttribute(LLVMValueRef Fn, LLVMAttribute PA) {
111   Function *A = unwrap<Function>(Fn);
112   AttrBuilder B(PA);
113   A->removeAttributes(AttributeSet::ReturnIndex,
114                       AttributeSet::get(A->getContext(), AttributeSet::ReturnIndex,  B));
115 }
116
117 #if LLVM_VERSION_MINOR >= 5
118 extern "C" void LLVMAddColdAttribute(LLVMValueRef Fn) {
119   Function *A = unwrap<Function>(Fn);
120   A->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
121 }
122 #else
123 extern "C" void LLVMAddColdAttribute(LLVMValueRef Fn) {}
124 #endif
125
126 extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
127                                             LLVMValueRef source,
128                                             const char* Name,
129                                             AtomicOrdering order,
130                                             unsigned alignment) {
131     LoadInst* li = new LoadInst(unwrap(source),0);
132     li->setVolatile(true);
133     li->setAtomic(order);
134     li->setAlignment(alignment);
135     return wrap(unwrap(B)->Insert(li, Name));
136 }
137
138 extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
139                                              LLVMValueRef val,
140                                              LLVMValueRef target,
141                                              AtomicOrdering order,
142                                              unsigned alignment) {
143     StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
144     si->setVolatile(true);
145     si->setAtomic(order);
146     si->setAlignment(alignment);
147     return wrap(unwrap(B)->Insert(si));
148 }
149
150 extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
151                                                LLVMValueRef target,
152                                                LLVMValueRef old,
153                                                LLVMValueRef source,
154                                                AtomicOrdering order,
155                                                AtomicOrdering failure_order) {
156     return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
157                                                unwrap(source), order
158 #if LLVM_VERSION_MINOR >= 5
159                                                , failure_order
160 #endif
161                                                ));
162 }
163 extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
164     return wrap(unwrap(B)->CreateFence(order));
165 }
166
167 extern "C" void LLVMSetDebug(int Enabled) {
168 #ifndef NDEBUG
169   DebugFlag = Enabled;
170 #endif
171 }
172
173 extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
174                                       char *AsmString,
175                                       char *Constraints,
176                                       LLVMBool HasSideEffects,
177                                       LLVMBool IsAlignStack,
178                                       unsigned Dialect) {
179     return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
180                                Constraints, HasSideEffects,
181                                IsAlignStack, (InlineAsm::AsmDialect) Dialect));
182 }
183
184 typedef DIBuilder* DIBuilderRef;
185
186 template<typename DIT>
187 DIT unwrapDI(LLVMValueRef ref) {
188     return DIT(ref ? unwrap<MDNode>(ref) : NULL);
189 }
190
191 #if LLVM_VERSION_MINOR >= 5
192 extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION;
193 #else
194 extern "C" const uint32_t LLVMRustDebugMetadataVersion = 1;
195 #endif
196
197 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
198                                       const char *name,
199                                       uint32_t value) {
200     unwrap(M)->addModuleFlag(Module::Warning, name, value);
201 }
202
203 extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
204     return new DIBuilder(*unwrap(M));
205 }
206
207 extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
208     delete Builder;
209 }
210
211 extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
212     Builder->finalize();
213 }
214
215 extern "C" void LLVMDIBuilderCreateCompileUnit(
216     DIBuilderRef Builder,
217     unsigned Lang,
218     const char* File,
219     const char* Dir,
220     const char* Producer,
221     bool isOptimized,
222     const char* Flags,
223     unsigned RuntimeVer,
224     const char* SplitName) {
225     Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
226         Flags, RuntimeVer, SplitName);
227 }
228
229 extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
230     DIBuilderRef Builder,
231     const char* Filename,
232     const char* Directory) {
233     return wrap(Builder->createFile(Filename, Directory));
234 }
235
236 extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
237     DIBuilderRef Builder,
238     LLVMValueRef File,
239     LLVMValueRef ParameterTypes) {
240     return wrap(Builder->createSubroutineType(
241         unwrapDI<DIFile>(File),
242         unwrapDI<DIArray>(ParameterTypes)));
243 }
244
245 extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
246     DIBuilderRef Builder,
247     LLVMValueRef Scope,
248     const char* Name,
249     const char* LinkageName,
250     LLVMValueRef File,
251     unsigned LineNo,
252     LLVMValueRef Ty,
253     bool isLocalToUnit,
254     bool isDefinition,
255     unsigned ScopeLine,
256     unsigned Flags,
257     bool isOptimized,
258     LLVMValueRef Fn,
259     LLVMValueRef TParam,
260     LLVMValueRef Decl) {
261     return wrap(Builder->createFunction(
262         unwrapDI<DIScope>(Scope), Name, LinkageName,
263         unwrapDI<DIFile>(File), LineNo,
264         unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
265         Flags, isOptimized,
266         unwrap<Function>(Fn),
267         unwrapDI<MDNode*>(TParam),
268         unwrapDI<MDNode*>(Decl)));
269 }
270
271 extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType(
272     DIBuilderRef Builder,
273     const char* Name,
274     uint64_t SizeInBits,
275     uint64_t AlignInBits,
276     unsigned Encoding) {
277     return wrap(Builder->createBasicType(
278         Name, SizeInBits,
279         AlignInBits, Encoding));
280 }
281
282 extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
283     DIBuilderRef Builder,
284     LLVMValueRef PointeeTy,
285     uint64_t SizeInBits,
286     uint64_t AlignInBits,
287     const char* Name) {
288     return wrap(Builder->createPointerType(
289         unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
290 }
291
292 extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
293     DIBuilderRef Builder,
294     LLVMValueRef Scope,
295     const char* Name,
296     LLVMValueRef File,
297     unsigned LineNumber,
298     uint64_t SizeInBits,
299     uint64_t AlignInBits,
300     unsigned Flags,
301     LLVMValueRef DerivedFrom,
302     LLVMValueRef Elements,
303     unsigned RunTimeLang,
304     LLVMValueRef VTableHolder,
305     const char *UniqueId) {
306     return wrap(Builder->createStructType(
307         unwrapDI<DIDescriptor>(Scope),
308         Name,
309         unwrapDI<DIFile>(File),
310         LineNumber,
311         SizeInBits,
312         AlignInBits,
313         Flags,
314         unwrapDI<DIType>(DerivedFrom),
315         unwrapDI<DIArray>(Elements),
316         RunTimeLang,
317         unwrapDI<DIType>(VTableHolder)
318 #if LLVM_VERSION_MINOR >= 5
319         ,UniqueId
320 #endif
321         ));
322 }
323
324 extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType(
325     DIBuilderRef Builder,
326     LLVMValueRef Scope,
327     const char* Name,
328     LLVMValueRef File,
329     unsigned LineNo,
330     uint64_t SizeInBits,
331     uint64_t AlignInBits,
332     uint64_t OffsetInBits,
333     unsigned Flags,
334     LLVMValueRef Ty) {
335     return wrap(Builder->createMemberType(
336         unwrapDI<DIDescriptor>(Scope), Name,
337         unwrapDI<DIFile>(File), LineNo,
338         SizeInBits, AlignInBits, OffsetInBits, Flags,
339         unwrapDI<DIType>(Ty)));
340 }
341
342 extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
343     DIBuilderRef Builder,
344     LLVMValueRef Scope,
345     LLVMValueRef File,
346     unsigned Line,
347     unsigned Col,
348     unsigned Discriminator) {
349     return wrap(Builder->createLexicalBlock(
350         unwrapDI<DIDescriptor>(Scope),
351         unwrapDI<DIFile>(File), Line, Col
352 #if LLVM_VERSION_MINOR >= 5
353         , Discriminator
354 #endif
355         ));
356 }
357
358 extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable(
359     DIBuilderRef Builder,
360     LLVMValueRef Context,
361     const char* Name,
362     const char* LinkageName,
363     LLVMValueRef File,
364     unsigned LineNo,
365     LLVMValueRef Ty,
366     bool isLocalToUnit,
367     LLVMValueRef Val,
368     LLVMValueRef Decl = NULL) {
369     return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
370         Name,
371         LinkageName,
372         unwrapDI<DIFile>(File),
373         LineNo,
374         unwrapDI<DIType>(Ty),
375         isLocalToUnit,
376         unwrap(Val),
377         unwrapDI<MDNode*>(Decl)));
378 }
379
380 extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
381     DIBuilderRef Builder,
382     unsigned Tag,
383     LLVMValueRef Scope,
384     const char* Name,
385     LLVMValueRef File,
386     unsigned LineNo,
387     LLVMValueRef Ty,
388     bool AlwaysPreserve,
389     unsigned Flags,
390     unsigned ArgNo) {
391     return wrap(Builder->createLocalVariable(Tag,
392         unwrapDI<DIDescriptor>(Scope), Name,
393         unwrapDI<DIFile>(File),
394         LineNo,
395         unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
396 }
397
398 extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
399     DIBuilderRef Builder,
400     uint64_t Size,
401     uint64_t AlignInBits,
402     LLVMValueRef Ty,
403     LLVMValueRef Subscripts) {
404     return wrap(Builder->createArrayType(Size, AlignInBits,
405         unwrapDI<DIType>(Ty),
406         unwrapDI<DIArray>(Subscripts)));
407 }
408
409 extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType(
410     DIBuilderRef Builder,
411     uint64_t Size,
412     uint64_t AlignInBits,
413     LLVMValueRef Ty,
414     LLVMValueRef Subscripts) {
415     return wrap(Builder->createVectorType(Size, AlignInBits,
416         unwrapDI<DIType>(Ty),
417         unwrapDI<DIArray>(Subscripts)));
418 }
419
420 extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(
421     DIBuilderRef Builder,
422     int64_t Lo,
423     int64_t Count) {
424     return wrap(Builder->getOrCreateSubrange(Lo, Count));
425 }
426
427 extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
428     DIBuilderRef Builder,
429     LLVMValueRef* Ptr,
430     unsigned Count) {
431     return wrap(Builder->getOrCreateArray(
432         ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
433 }
434
435 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
436     DIBuilderRef Builder,
437     LLVMValueRef Val,
438     LLVMValueRef VarInfo,
439     LLVMBasicBlockRef InsertAtEnd) {
440     return wrap(Builder->insertDeclare(
441         unwrap(Val),
442         unwrapDI<DIVariable>(VarInfo),
443         unwrap(InsertAtEnd)));
444 }
445
446 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
447     DIBuilderRef Builder,
448     LLVMValueRef Val,
449     LLVMValueRef VarInfo,
450     LLVMValueRef InsertBefore) {
451     return wrap(Builder->insertDeclare(
452         unwrap(Val),
453         unwrapDI<DIVariable>(VarInfo),
454         unwrap<Instruction>(InsertBefore)));
455 }
456
457 extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator(
458     DIBuilderRef Builder,
459     const char* Name,
460     uint64_t Val)
461 {
462     return wrap(Builder->createEnumerator(Name, Val));
463 }
464
465 extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType(
466     DIBuilderRef Builder,
467     LLVMValueRef Scope,
468     const char* Name,
469     LLVMValueRef File,
470     unsigned LineNumber,
471     uint64_t SizeInBits,
472     uint64_t AlignInBits,
473     LLVMValueRef Elements,
474     LLVMValueRef ClassType)
475 {
476     return wrap(Builder->createEnumerationType(
477         unwrapDI<DIDescriptor>(Scope),
478         Name,
479         unwrapDI<DIFile>(File),
480         LineNumber,
481         SizeInBits,
482         AlignInBits,
483         unwrapDI<DIArray>(Elements),
484         unwrapDI<DIType>(ClassType)));
485 }
486
487 extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
488     DIBuilderRef Builder,
489     LLVMValueRef Scope,
490     const char* Name,
491     LLVMValueRef File,
492     unsigned LineNumber,
493     uint64_t SizeInBits,
494     uint64_t AlignInBits,
495     unsigned Flags,
496     LLVMValueRef Elements,
497     unsigned RunTimeLang,
498     const char* UniqueId)
499 {
500     return wrap(Builder->createUnionType(
501         unwrapDI<DIDescriptor>(Scope),
502         Name,
503         unwrapDI<DIFile>(File),
504         LineNumber,
505         SizeInBits,
506         AlignInBits,
507         Flags,
508         unwrapDI<DIArray>(Elements),
509         RunTimeLang
510 #if LLVM_VERSION_MINOR >= 5
511         ,UniqueId
512 #endif
513         ));
514 }
515
516 #if LLVM_VERSION_MINOR < 5
517 extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
518     unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
519 }
520 #endif
521
522 extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
523     DIBuilderRef Builder,
524     LLVMValueRef Scope,
525     const char* Name,
526     LLVMValueRef Ty,
527     LLVMValueRef File,
528     unsigned LineNo,
529     unsigned ColumnNo)
530 {
531     return wrap(Builder->createTemplateTypeParameter(
532       unwrapDI<DIDescriptor>(Scope),
533       Name,
534       unwrapDI<DIType>(Ty),
535       unwrapDI<MDNode*>(File),
536       LineNo,
537       ColumnNo));
538 }
539
540 extern "C" LLVMValueRef LLVMDIBuilderCreateOpDeref(LLVMTypeRef IntTy)
541 {
542     return LLVMConstInt(IntTy, DIBuilder::OpDeref, true);
543 }
544
545 extern "C" LLVMValueRef LLVMDIBuilderCreateOpPlus(LLVMTypeRef IntTy)
546 {
547     return LLVMConstInt(IntTy, DIBuilder::OpPlus, true);
548 }
549
550 extern "C" LLVMValueRef LLVMDIBuilderCreateComplexVariable(
551     DIBuilderRef Builder,
552     unsigned Tag,
553     LLVMValueRef Scope,
554     const char *Name,
555     LLVMValueRef File,
556     unsigned LineNo,
557     LLVMValueRef Ty,
558     LLVMValueRef* AddrOps,
559     unsigned AddrOpsCount,
560     unsigned ArgNo)
561 {
562     llvm::ArrayRef<llvm::Value*> addr_ops((llvm::Value**)AddrOps, AddrOpsCount);
563
564     return wrap(Builder->createComplexVariable(
565         Tag,
566         unwrapDI<DIDescriptor>(Scope),
567         Name,
568         unwrapDI<DIFile>(File),
569         LineNo,
570         unwrapDI<DIType>(Ty),
571         addr_ops,
572         ArgNo
573     ));
574 }
575
576 extern "C" LLVMValueRef LLVMDIBuilderCreateNameSpace(
577     DIBuilderRef Builder,
578     LLVMValueRef Scope,
579     const char* Name,
580     LLVMValueRef File,
581     unsigned LineNo)
582 {
583     return wrap(Builder->createNameSpace(
584         unwrapDI<DIDescriptor>(Scope),
585         Name,
586         unwrapDI<DIFile>(File),
587         LineNo));
588 }
589
590 extern "C" void LLVMDICompositeTypeSetTypeArray(
591     LLVMValueRef CompositeType,
592     LLVMValueRef TypeArray)
593 {
594     unwrapDI<DICompositeType>(CompositeType).setTypeArray(unwrapDI<DIArray>(TypeArray));
595 }
596
597 extern "C" char *LLVMTypeToString(LLVMTypeRef Type) {
598     std::string s;
599     llvm::raw_string_ostream os(s);
600     unwrap<llvm::Type>(Type)->print(os);
601     return strdup(os.str().data());
602 }
603
604 extern "C" char *LLVMValueToString(LLVMValueRef Value) {
605     std::string s;
606     llvm::raw_string_ostream os(s);
607     os << "(";
608     unwrap<llvm::Value>(Value)->getType()->print(os);
609     os << ":";
610     unwrap<llvm::Value>(Value)->print(os);
611     os << ")";
612     return strdup(os.str().data());
613 }
614
615 #if LLVM_VERSION_MINOR >= 5
616 extern "C" bool
617 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
618     Module *Dst = unwrap(dst);
619     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
620     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
621     if (!Src) {
622         LLVMRustSetLastError(Src.getError().message().c_str());
623         delete buf;
624         return false;
625     }
626
627     std::string Err;
628     if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
629         LLVMRustSetLastError(Err.c_str());
630         return false;
631     }
632     return true;
633 }
634 #else
635 extern "C" bool
636 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
637     Module *Dst = unwrap(dst);
638     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
639     std::string Err;
640     Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err);
641     if (!Src) {
642         LLVMRustSetLastError(Err.c_str());
643         delete buf;
644         return false;
645     }
646
647     if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) {
648         LLVMRustSetLastError(Err.c_str());
649         return false;
650     }
651     return true;
652 }
653 #endif
654
655 #if LLVM_VERSION_MINOR >= 5
656 extern "C" void*
657 LLVMRustOpenArchive(char *path) {
658     std::unique_ptr<MemoryBuffer> buf;
659     error_code err = MemoryBuffer::getFile(path, buf);
660     if (err) {
661         LLVMRustSetLastError(err.message().c_str());
662         return NULL;
663     }
664     Archive *ret = new Archive(buf.release(), err);
665     if (err) {
666         LLVMRustSetLastError(err.message().c_str());
667         return NULL;
668     }
669     return ret;
670 }
671 #else
672 extern "C" void*
673 LLVMRustOpenArchive(char *path) {
674     OwningPtr<MemoryBuffer> buf;
675     error_code err = MemoryBuffer::getFile(path, buf);
676     if (err) {
677         LLVMRustSetLastError(err.message().c_str());
678         return NULL;
679     }
680     Archive *ret = new Archive(buf.take(), err);
681     if (err) {
682         LLVMRustSetLastError(err.message().c_str());
683         return NULL;
684     }
685     return ret;
686 }
687 #endif
688
689 extern "C" const char*
690 LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) {
691 #if LLVM_VERSION_MINOR >= 5
692     Archive::child_iterator child = ar->child_begin(),
693                               end = ar->child_end();
694 #else
695     Archive::child_iterator child = ar->begin_children(),
696                               end = ar->end_children();
697 #endif
698     for (; child != end; ++child) {
699         StringRef sect_name;
700         error_code err = child->getName(sect_name);
701         if (err) continue;
702         if (sect_name.trim(" ") == name) {
703             StringRef buf = child->getBuffer();
704             *size = buf.size();
705             return buf.data();
706         }
707     }
708     return NULL;
709 }
710
711 extern "C" void
712 LLVMRustDestroyArchive(Archive *ar) {
713     delete ar;
714 }
715
716 #if LLVM_VERSION_MINOR >= 5
717 extern "C" void
718 LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
719     GlobalValue *V = unwrap<GlobalValue>(Value);
720     V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
721 }
722 #else
723 extern "C" void
724 LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
725     LLVMSetLinkage(Value, LLVMDLLExportLinkage);
726 }
727 #endif
728
729 extern "C" int
730 LLVMVersionMinor() {
731     return LLVM_VERSION_MINOR;
732 }
733
734 // Note that the two following functions look quite similar to the
735 // LLVMGetSectionName function. Sadly, it appears that this function only
736 // returns a char* pointer, which isn't guaranteed to be null-terminated. The
737 // function provided by LLVM doesn't return the length, so we've created our own
738 // function which returns the length as well as the data pointer.
739 //
740 // For an example of this not returning a null terminated string, see
741 // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
742 // branches explicitly creates a StringRef without a null terminator, and then
743 // that's returned.
744
745 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
746     return reinterpret_cast<section_iterator*>(SI);
747 }
748
749 extern "C" int
750 LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
751     StringRef ret;
752     if (error_code ec = (*unwrap(SI))->getName(ret))
753       report_fatal_error(ec.message());
754     *ptr = ret.data();
755     return ret.size();
756 }