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