// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #include "rustllvm.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/CallSite.h" //===----------------------------------------------------------------------=== // // This file defines alternate interfaces to core functions that are more // readily callable by Rust's FFI. // //===----------------------------------------------------------------------=== using namespace llvm; using namespace llvm::sys; using namespace llvm::object; static char *LastError; extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { ErrorOr> buf_or = MemoryBuffer::getFile(Path, -1, false); if (!buf_or) { LLVMRustSetLastError(buf_or.getError().message().c_str()); return nullptr; } return wrap(buf_or.get().release()); } extern "C" char *LLVMRustGetLastError(void) { char *ret = LastError; LastError = NULL; return ret; } void LLVMRustSetLastError(const char *err) { free((void*) LastError); LastError = strdup(err); } extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) { unwrap(M)->setTargetTriple(Triple::normalize(triple)); } extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N, LLVMBool SignExtend) { return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend); } extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy, unsigned N_hi, unsigned N_lo, LLVMBool SignExtend) { unsigned long long N = N_hi; N <<= 32; N |= N_lo; return LLVMConstInt(IntTy, N, SignExtend); } extern "C" void LLVMRustPrintPassTimings() { raw_fd_ostream OS (2, false); // stderr. TimerGroup::printAll(OS); } extern "C" LLVMValueRef LLVMGetNamedValue(LLVMModuleRef M, const char* Name) { return wrap(unwrap(M)->getNamedValue(Name)); } extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, const char* Name, LLVMTypeRef FunctionTy) { return wrap(unwrap(M)->getOrInsertFunction(Name, unwrap(FunctionTy))); } extern "C" LLVMValueRef LLVMGetOrInsertGlobal(LLVMModuleRef M, const char* Name, LLVMTypeRef Ty) { return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty))); } extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { return wrap(Type::getMetadataTy(*unwrap(C))); } extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) { CallSite Call = CallSite(unwrap(Instr)); AttrBuilder B; B.addRawValue(Val); Call.setAttributes( Call.getAttributes().addAttributes(Call->getContext(), index, AttributeSet::get(Call->getContext(), index, B))); } extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) { CallSite Call = CallSite(unwrap(Instr)); AttrBuilder B; B.addDereferenceableAttr(b); Call.setAttributes( Call.getAttributes().addAttributes(Call->getContext(), idx, AttributeSet::get(Call->getContext(), idx, B))); } extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64_t Val) { Function *A = unwrap(Fn); AttrBuilder B; B.addRawValue(Val); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) { Function *A = unwrap(Fn); AttrBuilder B; B.addDereferenceableAttr(bytes); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) { Function *F = unwrap(Fn); AttrBuilder B; B.addAttribute(Name); F->addAttributes(index, AttributeSet::get(F->getContext(), index, B)); } extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) { Function *f = unwrap(fn); LLVMContext &C = f->getContext(); AttrBuilder B; B.addAttribute(Name); AttributeSet to_remove = AttributeSet::get(C, index, B); AttributeSet attrs = f->getAttributes(); f->setAttributes(attrs.removeAttributes(f->getContext(), index, to_remove)); } extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef source, const char* Name, AtomicOrdering order, unsigned alignment) { LoadInst* li = new LoadInst(unwrap(source),0); li->setVolatile(true); li->setAtomic(order); li->setAlignment(alignment); return wrap(unwrap(B)->Insert(li, Name)); } extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef val, LLVMValueRef target, AtomicOrdering order, unsigned alignment) { StoreInst* si = new StoreInst(unwrap(val),unwrap(target)); si->setVolatile(true); si->setAtomic(order); si->setAlignment(alignment); return wrap(unwrap(B)->Insert(si)); } extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef target, LLVMValueRef old, LLVMValueRef source, AtomicOrdering order, AtomicOrdering failure_order) { return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old), unwrap(source), order, failure_order )); } extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order, SynchronizationScope scope) { return wrap(unwrap(B)->CreateFence(order, scope)); } extern "C" void LLVMSetDebug(int Enabled) { #ifndef NDEBUG DebugFlag = Enabled; #endif } extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, char *AsmString, char *Constraints, LLVMBool HasSideEffects, LLVMBool IsAlignStack, unsigned Dialect) { return wrap(InlineAsm::get(unwrap(Ty), AsmString, Constraints, HasSideEffects, IsAlignStack, (InlineAsm::AsmDialect) Dialect)); } typedef DIBuilder* DIBuilderRef; #if LLVM_VERSION_MINOR >= 6 typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; namespace llvm { DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) inline Metadata **unwrap(LLVMMetadataRef *Vals) { return reinterpret_cast(Vals); } } #else typedef LLVMValueRef LLVMMetadataRef; #endif template DIT unwrapDI(LLVMMetadataRef ref) { return DIT(ref ? unwrap(ref) : NULL); } extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION; extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *name, uint32_t value) { unwrap(M)->addModuleFlag(Module::Warning, name, value); } extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) { return new DIBuilder(*unwrap(M)); } extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) { delete Builder; } extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) { Builder->finalize(); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( DIBuilderRef Builder, unsigned Lang, const char* File, const char* Dir, const char* Producer, bool isOptimized, const char* Flags, unsigned RuntimeVer, const char* SplitName) { return wrap(Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized, Flags, RuntimeVer, SplitName)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile( DIBuilderRef Builder, const char* Filename, const char* Directory) { return wrap(Builder->createFile(Filename, Directory)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType( DIBuilderRef Builder, LLVMMetadataRef File, LLVMMetadataRef ParameterTypes) { return wrap(Builder->createSubroutineType( unwrapDI(File), #if LLVM_VERSION_MINOR >= 6 unwrapDI(ParameterTypes))); #else unwrapDI(ParameterTypes))); #endif } extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, const char* LinkageName, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags, bool isOptimized, LLVMValueRef Fn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) { return wrap(Builder->createFunction( unwrapDI(Scope), Name, LinkageName, unwrapDI(File), LineNo, unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, Flags, isOptimized, unwrap(Fn), unwrapDI(TParam), unwrapDI(Decl))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType( DIBuilderRef Builder, const char* Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding) { return wrap(Builder->createBasicType( Name, SizeInBits, AlignInBits, Encoding)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType( DIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits, const char* Name) { return wrap(Builder->createPointerType( unwrapDI(PointeeTy), SizeInBits, AlignInBits, Name)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder, const char *UniqueId) { return wrap(Builder->createStructType( unwrapDI(Scope), Name, unwrapDI(File), LineNumber, SizeInBits, AlignInBits, Flags, unwrapDI(DerivedFrom), unwrapDI(Elements), RunTimeLang, unwrapDI(VTableHolder), UniqueId )); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, LLVMMetadataRef Ty) { return wrap(Builder->createMemberType( unwrapDI(Scope), Name, unwrapDI(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, Flags, unwrapDI(Ty))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock( DIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, unsigned Col) { return wrap(Builder->createLexicalBlock( unwrapDI(Scope), unwrapDI(File), Line, Col #if LLVM_VERSION_MINOR == 5 , 0 #endif )); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable( DIBuilderRef Builder, LLVMMetadataRef Context, const char* Name, const char* LinkageName, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool isLocalToUnit, LLVMValueRef Val, LLVMMetadataRef Decl = NULL) { #if LLVM_VERSION_MINOR >= 6 return wrap(Builder->createGlobalVariable(unwrapDI(Context), #else return wrap(Builder->createStaticVariable(unwrapDI(Context), #endif Name, LinkageName, unwrapDI(File), LineNo, unwrapDI(Ty), isLocalToUnit, cast(unwrap(Val)), unwrapDI(Decl))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( DIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool AlwaysPreserve, unsigned Flags, int64_t* AddrOps, unsigned AddrOpsCount, unsigned ArgNo) { #if LLVM_VERSION_MINOR == 5 if (AddrOpsCount > 0) { SmallVector addr_ops; llvm::Type *Int64Ty = Type::getInt64Ty(unwrap(Scope)->getContext()); for (unsigned i = 0; i < AddrOpsCount; ++i) addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i])); return wrap(Builder->createComplexVariable( Tag, unwrapDI(Scope), Name, unwrapDI(File), LineNo, unwrapDI(Ty), addr_ops, ArgNo )); } #endif return wrap(Builder->createLocalVariable(Tag, unwrapDI(Scope), Name, unwrapDI(File), LineNo, unwrapDI(Ty), AlwaysPreserve, Flags, ArgNo)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType( DIBuilderRef Builder, uint64_t Size, uint64_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef Subscripts) { return wrap(Builder->createArrayType(Size, AlignInBits, unwrapDI(Ty), unwrapDI(Subscripts))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType( DIBuilderRef Builder, uint64_t Size, uint64_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef Subscripts) { return wrap(Builder->createVectorType(Size, AlignInBits, unwrapDI(Ty), unwrapDI(Subscripts))); } extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange( DIBuilderRef Builder, int64_t Lo, int64_t Count) { return wrap(Builder->getOrCreateSubrange(Lo, Count)); } extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray( DIBuilderRef Builder, LLVMMetadataRef* Ptr, unsigned Count) { return wrap(Builder->getOrCreateArray( #if LLVM_VERSION_MINOR >= 6 ArrayRef(unwrap(Ptr), Count))); #else ArrayRef(reinterpret_cast(Ptr), Count))); #endif } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( DIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, int64_t* AddrOps, unsigned AddrOpsCount, LLVMBasicBlockRef InsertAtEnd) { #if LLVM_VERSION_MINOR >= 6 DIExpression Expr; if (AddrOpsCount == 0) { Expr = Builder->createExpression(); } else { llvm::ArrayRef addr_ops(AddrOps, AddrOpsCount); Expr = Builder->createExpression(addr_ops); } #endif return wrap(Builder->insertDeclare( unwrap(Val), unwrapDI(VarInfo), #if LLVM_VERSION_MINOR >= 6 Expr, #endif unwrap(InsertAtEnd))); } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore( DIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, int64_t* AddrOps, unsigned AddrOpsCount, LLVMValueRef InsertBefore) { #if LLVM_VERSION_MINOR >= 6 DIExpression Expr; if (AddrOpsCount == 0) { Expr = Builder->createExpression(); } else { llvm::ArrayRef addr_ops(AddrOps, AddrOpsCount); Expr = Builder->createExpression(addr_ops); } #endif return wrap(Builder->insertDeclare( unwrap(Val), unwrapDI(VarInfo), #if LLVM_VERSION_MINOR >= 6 Expr, #endif unwrap(InsertBefore))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator( DIBuilderRef Builder, const char* Name, uint64_t Val) { return wrap(Builder->createEnumerator(Name, Val)); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, LLVMMetadataRef Elements, LLVMMetadataRef ClassType) { return wrap(Builder->createEnumerationType( unwrapDI(Scope), Name, unwrapDI(File), LineNumber, SizeInBits, AlignInBits, unwrapDI(Elements), unwrapDI(ClassType))); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef Elements, unsigned RunTimeLang, const char* UniqueId) { return wrap(Builder->createUnionType( unwrapDI(Scope), Name, unwrapDI(File), LineNumber, SizeInBits, AlignInBits, Flags, unwrapDI(Elements), RunTimeLang, UniqueId )); } extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo, unsigned ColumnNo) { return wrap(Builder->createTemplateTypeParameter( unwrapDI(Scope), Name, unwrapDI(Ty), unwrapDI(File), LineNo, ColumnNo)); } extern "C" int64_t LLVMDIBuilderCreateOpDeref() { return dwarf::DW_OP_deref; } extern "C" int64_t LLVMDIBuilderCreateOpPlus() { return dwarf::DW_OP_plus; } extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace( DIBuilderRef Builder, LLVMMetadataRef Scope, const char* Name, LLVMMetadataRef File, unsigned LineNo) { return wrap(Builder->createNameSpace( unwrapDI(Scope), Name, unwrapDI(File), LineNo)); } extern "C" void LLVMDICompositeTypeSetTypeArray( DIBuilderRef Builder, LLVMMetadataRef CompositeType, LLVMMetadataRef TypeArray) { #if LLVM_VERSION_MINOR >= 6 DICompositeType tmp = unwrapDI(CompositeType); Builder->replaceArrays(tmp, unwrapDI(TypeArray)); #else unwrapDI(CompositeType).setTypeArray(unwrapDI(TypeArray)); #endif } extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation( LLVMContextRef Context, unsigned Line, unsigned Column, LLVMMetadataRef Scope, LLVMMetadataRef InlinedAt) { LLVMContext& context = *unwrap(Context); DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDI(Scope), unwrapDI(InlinedAt)); #if LLVM_VERSION_MINOR >= 6 return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context))); #else return wrap(debug_loc.getAsMDNode(context)); #endif } extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) { raw_rust_string_ostream os(str); unwrap(Type)->print(os); } extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) { raw_rust_string_ostream os(str); os << "("; unwrap(Value)->getType()->print(os); os << ":"; unwrap(Value)->print(os); os << ")"; } extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { Module *Dst = unwrap(dst); #if LLVM_VERSION_MINOR >= 6 std::unique_ptr buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); ErrorOr Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext()); #else MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); ErrorOr Src = llvm::getLazyBitcodeModule(buf, Dst->getContext()); #endif if (!Src) { LLVMRustSetLastError(Src.getError().message().c_str()); #if LLVM_VERSION_MINOR == 5 delete buf; #endif return false; } std::string Err; #if LLVM_VERSION_MINOR >= 6 raw_string_ostream Stream(Err); DiagnosticPrinterRawOStream DP(Stream); if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) { #else if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) { #endif LLVMRustSetLastError(Err.c_str()); return false; } return true; } extern "C" void* LLVMRustOpenArchive(char *path) { ErrorOr> buf_or = MemoryBuffer::getFile(path, -1, false); if (!buf_or) { LLVMRustSetLastError(buf_or.getError().message().c_str()); return nullptr; } #if LLVM_VERSION_MINOR >= 6 ErrorOr> archive_or = Archive::create(buf_or.get()->getMemBufferRef()); if (!archive_or) { LLVMRustSetLastError(archive_or.getError().message().c_str()); return nullptr; } OwningBinary *ret = new OwningBinary( std::move(archive_or.get()), std::move(buf_or.get())); #else std::error_code err; Archive *ret = new Archive(std::move(buf_or.get()), err); if (err) { LLVMRustSetLastError(err.message().c_str()); return nullptr; } #endif return ret; } #if LLVM_VERSION_MINOR >= 6 typedef OwningBinary RustArchive; #define GET_ARCHIVE(a) ((a)->getBinary()) #else typedef Archive RustArchive; #define GET_ARCHIVE(a) (a) #endif extern "C" void LLVMRustDestroyArchive(RustArchive *ar) { delete ar; } struct RustArchiveIterator { Archive::child_iterator cur; Archive::child_iterator end; }; extern "C" RustArchiveIterator* LLVMRustArchiveIteratorNew(RustArchive *ra) { Archive *ar = GET_ARCHIVE(ra); RustArchiveIterator *rai = new RustArchiveIterator(); rai->cur = ar->child_begin(); rai->end = ar->child_end(); return rai; } extern "C" const Archive::Child* LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) { if (rai->cur == rai->end) return NULL; const Archive::Child &ret = *rai->cur; return &ret; } extern "C" void LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) { if (rai->cur == rai->end) return; ++rai->cur; } extern "C" void LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) { delete rai; } extern "C" const char* LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) { ErrorOr name_or_err = child->getName(); if (name_or_err.getError()) return NULL; StringRef name = name_or_err.get(); *size = name.size(); return name.data(); } extern "C" const char* LLVMRustArchiveChildData(Archive::Child *child, size_t *size) { StringRef buf = child->getBuffer(); *size = buf.size(); return buf.data(); } extern "C" void LLVMRustSetDLLStorageClass(LLVMValueRef Value, GlobalValue::DLLStorageClassTypes Class) { GlobalValue *V = unwrap(Value); V->setDLLStorageClass(Class); } // Note that the two following functions look quite similar to the // LLVMGetSectionName function. Sadly, it appears that this function only // returns a char* pointer, which isn't guaranteed to be null-terminated. The // function provided by LLVM doesn't return the length, so we've created our own // function which returns the length as well as the data pointer. // // For an example of this not returning a null terminated string, see // lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the // branches explicitly creates a StringRef without a null terminator, and then // that's returned. inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { return reinterpret_cast(SI); } extern "C" int LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) { StringRef ret; if (std::error_code ec = (*unwrap(SI))->getName(ret)) report_fatal_error(ec.message()); *ptr = ret.data(); return ret.size(); } // LLVMArrayType function does not support 64-bit ElementCount extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) { return wrap(ArrayType::get(unwrap(ElementType), ElementCount)); } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef) extern "C" void LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) { raw_rust_string_ostream os(str); unwrap(T)->print(os); } extern "C" void LLVMUnpackOptimizationDiagnostic( LLVMDiagnosticInfoRef di, const char **pass_name_out, LLVMValueRef *function_out, LLVMDebugLocRef *debugloc_out, LLVMTwineRef *message_out) { // Undefined to call this not on an optimization diagnostic! llvm::DiagnosticInfoOptimizationBase *opt = static_cast(unwrap(di)); *pass_name_out = opt->getPassName(); *function_out = wrap(&opt->getFunction()); *debugloc_out = wrap(&opt->getDebugLoc()); *message_out = wrap(&opt->getMsg()); } extern "C" void LLVMUnpackInlineAsmDiagnostic( LLVMDiagnosticInfoRef di, unsigned *cookie_out, LLVMTwineRef *message_out, LLVMValueRef *instruction_out) { // Undefined to call this not on an inline assembly diagnostic! llvm::DiagnosticInfoInlineAsm *ia = static_cast(unwrap(di)); *cookie_out = ia->getLocCookie(); *message_out = wrap(&ia->getMsgStr()); *instruction_out = wrap(ia->getInstruction()); } extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) { raw_rust_string_ostream os(str); DiagnosticPrinterRawOStream dp(os); unwrap(di)->print(dp); } extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) { return unwrap(di)->getKind(); } extern "C" void LLVMWriteDebugLocToString( LLVMContextRef C, LLVMDebugLocRef dl, RustStringRef str) { raw_rust_string_ostream os(str); unwrap(dl)->print(*unwrap(C), os); } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) extern "C" void LLVMSetInlineAsmDiagnosticHandler( LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); } extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) { raw_rust_string_ostream os(str); unwrap(d)->print("", os); }