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