diff options
Diffstat (limited to 'src/rustllvm')
| -rw-r--r-- | src/rustllvm/.editorconfig | 6 | ||||
| -rw-r--r-- | src/rustllvm/ArchiveWrapper.cpp | 226 | ||||
| -rw-r--r-- | src/rustllvm/CoverageMappingWrapper.cpp | 70 | ||||
| -rw-r--r-- | src/rustllvm/Linker.cpp | 48 | ||||
| -rw-r--r-- | src/rustllvm/PassWrapper.cpp | 1655 | ||||
| -rw-r--r-- | src/rustllvm/README | 16 | ||||
| -rw-r--r-- | src/rustllvm/RustWrapper.cpp | 1721 | ||||
| -rw-r--r-- | src/rustllvm/rustllvm.h | 115 |
8 files changed, 0 insertions, 3857 deletions
diff --git a/src/rustllvm/.editorconfig b/src/rustllvm/.editorconfig deleted file mode 100644 index 865cd45f708..00000000000 --- a/src/rustllvm/.editorconfig +++ /dev/null @@ -1,6 +0,0 @@ -[*.{h,cpp}] -end_of_line = lf -insert_final_newline = true -charset = utf-8 -indent_style = space -indent_size = 2 diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp deleted file mode 100644 index 9ce614fda57..00000000000 --- a/src/rustllvm/ArchiveWrapper.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include "rustllvm.h" - -#include "llvm/Object/Archive.h" -#include "llvm/Object/ArchiveWriter.h" -#include "llvm/Support/Path.h" - -using namespace llvm; -using namespace llvm::object; - -struct RustArchiveMember { - const char *Filename; - const char *Name; - Archive::Child Child; - - RustArchiveMember() - : Filename(nullptr), Name(nullptr), - Child(nullptr, nullptr, nullptr) - { - } - ~RustArchiveMember() {} -}; - -struct RustArchiveIterator { - bool First; - Archive::child_iterator Cur; - Archive::child_iterator End; - std::unique_ptr<Error> Err; - - RustArchiveIterator(Archive::child_iterator Cur, Archive::child_iterator End, - std::unique_ptr<Error> Err) - : First(true), - Cur(Cur), - End(End), - Err(std::move(Err)) {} -}; - -enum class LLVMRustArchiveKind { - GNU, - BSD, - DARWIN, - COFF, -}; - -static Archive::Kind fromRust(LLVMRustArchiveKind Kind) { - switch (Kind) { - case LLVMRustArchiveKind::GNU: - return Archive::K_GNU; - case LLVMRustArchiveKind::BSD: - return Archive::K_BSD; - case LLVMRustArchiveKind::DARWIN: - return Archive::K_DARWIN; - case LLVMRustArchiveKind::COFF: - return Archive::K_COFF; - default: - report_fatal_error("Bad ArchiveKind."); - } -} - -typedef OwningBinary<Archive> *LLVMRustArchiveRef; -typedef RustArchiveMember *LLVMRustArchiveMemberRef; -typedef Archive::Child *LLVMRustArchiveChildRef; -typedef Archive::Child const *LLVMRustArchiveChildConstRef; -typedef RustArchiveIterator *LLVMRustArchiveIteratorRef; - -extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *Path) { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr = - MemoryBuffer::getFile(Path, -1, false); - if (!BufOr) { - LLVMRustSetLastError(BufOr.getError().message().c_str()); - return nullptr; - } - - Expected<std::unique_ptr<Archive>> ArchiveOr = - Archive::create(BufOr.get()->getMemBufferRef()); - - if (!ArchiveOr) { - LLVMRustSetLastError(toString(ArchiveOr.takeError()).c_str()); - return nullptr; - } - - OwningBinary<Archive> *Ret = new OwningBinary<Archive>( - std::move(ArchiveOr.get()), std::move(BufOr.get())); - - return Ret; -} - -extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) { - delete RustArchive; -} - -extern "C" LLVMRustArchiveIteratorRef -LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) { - Archive *Archive = RustArchive->getBinary(); -#if LLVM_VERSION_GE(10, 0) - std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success()); -#else - std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success()); -#endif - auto Cur = Archive->child_begin(*Err); - if (*Err) { - LLVMRustSetLastError(toString(std::move(*Err)).c_str()); - return nullptr; - } - auto End = Archive->child_end(); - return new RustArchiveIterator(Cur, End, std::move(Err)); -} - -extern "C" LLVMRustArchiveChildConstRef -LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef RAI) { - if (RAI->Cur == RAI->End) - return nullptr; - - // Advancing the iterator validates the next child, and this can - // uncover an error. LLVM requires that we check all Errors, - // so we only advance the iterator if we actually need to fetch - // the next child. - // This means we must not advance the iterator in the *first* call, - // but instead advance it *before* fetching the child in all later calls. - if (!RAI->First) { - ++RAI->Cur; - if (*RAI->Err) { - LLVMRustSetLastError(toString(std::move(*RAI->Err)).c_str()); - return nullptr; - } - } else { - RAI->First = false; - } - - if (RAI->Cur == RAI->End) - return nullptr; - - const Archive::Child &Child = *RAI->Cur.operator->(); - Archive::Child *Ret = new Archive::Child(Child); - - return Ret; -} - -extern "C" void LLVMRustArchiveChildFree(LLVMRustArchiveChildRef Child) { - delete Child; -} - -extern "C" void LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef RAI) { - delete RAI; -} - -extern "C" const char * -LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) { - Expected<StringRef> NameOrErr = Child->getName(); - if (!NameOrErr) { - // rustc_codegen_llvm currently doesn't use this error string, but it might be - // useful in the future, and in the mean time this tells LLVM that the - // error was not ignored and that it shouldn't abort the process. - LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str()); - return nullptr; - } - StringRef Name = NameOrErr.get(); - *Size = Name.size(); - return Name.data(); -} - -extern "C" const char *LLVMRustArchiveChildData(LLVMRustArchiveChildRef Child, - size_t *Size) { - StringRef Buf; - Expected<StringRef> BufOrErr = Child->getBuffer(); - if (!BufOrErr) { - LLVMRustSetLastError(toString(BufOrErr.takeError()).c_str()); - return nullptr; - } - Buf = BufOrErr.get(); - *Size = Buf.size(); - return Buf.data(); -} - -extern "C" LLVMRustArchiveMemberRef -LLVMRustArchiveMemberNew(char *Filename, char *Name, - LLVMRustArchiveChildRef Child) { - RustArchiveMember *Member = new RustArchiveMember; - Member->Filename = Filename; - Member->Name = Name; - if (Child) - Member->Child = *Child; - return Member; -} - -extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) { - delete Member; -} - -extern "C" LLVMRustResult -LLVMRustWriteArchive(char *Dst, size_t NumMembers, - const LLVMRustArchiveMemberRef *NewMembers, - bool WriteSymbtab, LLVMRustArchiveKind RustKind) { - - std::vector<NewArchiveMember> Members; - auto Kind = fromRust(RustKind); - - for (size_t I = 0; I < NumMembers; I++) { - auto Member = NewMembers[I]; - assert(Member->Name); - if (Member->Filename) { - Expected<NewArchiveMember> MOrErr = - NewArchiveMember::getFile(Member->Filename, true); - if (!MOrErr) { - LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); - return LLVMRustResult::Failure; - } - MOrErr->MemberName = sys::path::filename(MOrErr->MemberName); - Members.push_back(std::move(*MOrErr)); - } else { - Expected<NewArchiveMember> MOrErr = - NewArchiveMember::getOldMember(Member->Child, true); - if (!MOrErr) { - LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); - return LLVMRustResult::Failure; - } - Members.push_back(std::move(*MOrErr)); - } - } - - auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false); - if (!Result) - return LLVMRustResult::Success; - LLVMRustSetLastError(toString(std::move(Result)).c_str()); - - return LLVMRustResult::Failure; -} diff --git a/src/rustllvm/CoverageMappingWrapper.cpp b/src/rustllvm/CoverageMappingWrapper.cpp deleted file mode 100644 index 81aba0cbf7d..00000000000 --- a/src/rustllvm/CoverageMappingWrapper.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "rustllvm.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/LEB128.h" - -#include <iostream> - -using namespace llvm; - -extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( - const char* const Filenames[], - size_t FilenamesLen, - RustStringRef BufferOut) { - // LLVM 11's CoverageFilenamesSectionWriter uses its new `Version4` format, - // so we're manually writing the `Version3` format ourselves. - RawRustStringOstream OS(BufferOut); - encodeULEB128(FilenamesLen, OS); - for (size_t i = 0; i < FilenamesLen; i++) { - StringRef Filename(Filenames[i]); - encodeULEB128(Filename.size(), OS); - OS << Filename; - } -} - -extern "C" void LLVMRustCoverageWriteMappingToBuffer( - const unsigned *VirtualFileMappingIDs, - unsigned NumVirtualFileMappingIDs, - const coverage::CounterExpression *Expressions, - unsigned NumExpressions, - coverage::CounterMappingRegion *MappingRegions, - unsigned NumMappingRegions, - RustStringRef BufferOut) { - auto CoverageMappingWriter = coverage::CoverageMappingWriter( - makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), - makeArrayRef(Expressions, NumExpressions), - makeMutableArrayRef(MappingRegions, NumMappingRegions)); - RawRustStringOstream OS(BufferOut); - CoverageMappingWriter.write(OS); -} - -extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) { - StringRef FuncNameRef(FuncName); - return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef)); -} - -extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) { - StringRef NameRef(Name); - return IndexedInstrProf::ComputeHash(NameRef); -} - -extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - auto name = getInstrProfSectionName(IPSK_covmap, - TargetTriple.getObjectFormat()); - RawRustStringOstream OS(Str); - OS << name; -} - -extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { - auto name = getCoverageMappingVarName(); - RawRustStringOstream OS(Str); - OS << name; -} - -extern "C" uint32_t LLVMRustCoverageMappingVersion() { - return coverage::CovMapVersion::Version3; -} diff --git a/src/rustllvm/Linker.cpp b/src/rustllvm/Linker.cpp deleted file mode 100644 index 69176f9cb1f..00000000000 --- a/src/rustllvm/Linker.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "llvm/Linker/Linker.h" - -#include "rustllvm.h" - -using namespace llvm; - -struct RustLinker { - Linker L; - LLVMContext &Ctx; - - RustLinker(Module &M) : - L(M), - Ctx(M.getContext()) - {} -}; - -extern "C" RustLinker* -LLVMRustLinkerNew(LLVMModuleRef DstRef) { - Module *Dst = unwrap(DstRef); - - return new RustLinker(*Dst); -} - -extern "C" void -LLVMRustLinkerFree(RustLinker *L) { - delete L; -} - -extern "C" bool -LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) { - std::unique_ptr<MemoryBuffer> Buf = - MemoryBuffer::getMemBufferCopy(StringRef(BC, Len)); - - Expected<std::unique_ptr<Module>> SrcOrError = - llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), L->Ctx); - if (!SrcOrError) { - LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str()); - return false; - } - - auto Src = std::move(*SrcOrError); - - if (L->L.linkInModule(std::move(Src))) { - LLVMRustSetLastError(""); - return false; - } - return true; -} diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp deleted file mode 100644 index 76fe5e7f769..00000000000 --- a/src/rustllvm/PassWrapper.cpp +++ /dev/null @@ -1,1655 +0,0 @@ -#include <stdio.h> - -#include <vector> -#include <set> - -#include "rustllvm.h" - -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/InitializePasses.h" -#include "llvm/IR/AutoUpgrade.h" -#include "llvm/IR/AssemblyAnnotationWriter.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/IRObjectFile.h" -#include "llvm/Passes/PassBuilder.h" -#if LLVM_VERSION_GE(9, 0) -#include "llvm/Passes/StandardInstrumentations.h" -#endif -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/IPO/AlwaysInliner.h" -#include "llvm/Transforms/IPO/FunctionImport.h" -#include "llvm/Transforms/Utils/FunctionImportUtils.h" -#include "llvm/LTO/LTO.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" - -#include "llvm/Transforms/Instrumentation.h" -#if LLVM_VERSION_GE(9, 0) -#include "llvm/Transforms/Instrumentation/AddressSanitizer.h" -#include "llvm/Support/TimeProfiler.h" -#endif -#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" -#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" -#if LLVM_VERSION_GE(9, 0) -#include "llvm/Transforms/Utils/CanonicalizeAliases.h" -#endif -#include "llvm/Transforms/Utils/NameAnonGlobals.h" - -using namespace llvm; - -typedef struct LLVMOpaquePass *LLVMPassRef; -typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; - -DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) -DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -#if LLVM_VERSION_LT(11, 0) -DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, - LLVMPassManagerBuilderRef) -#endif - -extern "C" void LLVMInitializePasses() { - PassRegistry &Registry = *PassRegistry::getPassRegistry(); - initializeCore(Registry); - initializeCodeGen(Registry); - initializeScalarOpts(Registry); - initializeVectorization(Registry); - initializeIPO(Registry); - initializeAnalysis(Registry); - initializeTransformUtils(Registry); - initializeInstCombine(Registry); - initializeInstrumentation(Registry); - initializeTarget(Registry); -} - -extern "C" void LLVMTimeTraceProfilerInitialize() { -#if LLVM_VERSION_GE(10, 0) - timeTraceProfilerInitialize( - /* TimeTraceGranularity */ 0, - /* ProcName */ "rustc"); -#elif LLVM_VERSION_GE(9, 0) - timeTraceProfilerInitialize(); -#endif -} - -extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { -#if LLVM_VERSION_GE(9, 0) - StringRef FN(FileName); - std::error_code EC; - raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways); - - timeTraceProfilerWrite(OS); - timeTraceProfilerCleanup(); -#endif -} - -enum class LLVMRustPassKind { - Other, - Function, - Module, -}; - -static LLVMRustPassKind toRust(PassKind Kind) { - switch (Kind) { - case PT_Function: - return LLVMRustPassKind::Function; - case PT_Module: - return LLVMRustPassKind::Module; - default: - return LLVMRustPassKind::Other; - } -} - -extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { - StringRef SR(PassName); - PassRegistry *PR = PassRegistry::getPassRegistry(); - - const PassInfo *PI = PR->getPassInfo(SR); - if (PI) { - return wrap(PI->createPass()); - } - return nullptr; -} - -extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) { - const bool CompileKernel = false; - const bool UseAfterScope = true; - - return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope)); -} - -extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) { - const bool CompileKernel = false; - -#if LLVM_VERSION_GE(9, 0) - return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover)); -#else - return wrap(createAddressSanitizerModulePass(CompileKernel, Recover)); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) { -#if LLVM_VERSION_GE(9, 0) - const bool CompileKernel = false; - - return wrap(createMemorySanitizerLegacyPassPass( - MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel})); -#else - return wrap(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover)); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { - return wrap(createThreadSanitizerLegacyPassPass()); -} - -extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) { - assert(RustPass); - Pass *Pass = unwrap(RustPass); - return toRust(Pass->getPassKind()); -} - -extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { - assert(RustPass); - Pass *Pass = unwrap(RustPass); - PassManagerBase *PMB = unwrap(PMR); - PMB->add(Pass); -} - -extern "C" -void LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - LLVMPassManagerBuilderRef PMBR, - LLVMPassManagerRef PMR -) { - unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR)); -} - -extern "C" -void LLVMRustAddLastExtensionPasses( - LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) { - auto AddExtensionPasses = [Passes, NumPasses]( - const PassManagerBuilder &Builder, PassManagerBase &PM) { - for (size_t I = 0; I < NumPasses; I++) { - PM.add(unwrap(Passes[I])); - } - }; - // Add the passes to both of the pre-finalization extension points, - // so they are run for optimized and non-optimized builds. - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast, - AddExtensionPasses); - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - AddExtensionPasses); -} - -#ifdef LLVM_COMPONENT_X86 -#define SUBTARGET_X86 SUBTARGET(X86) -#else -#define SUBTARGET_X86 -#endif - -#ifdef LLVM_COMPONENT_ARM -#define SUBTARGET_ARM SUBTARGET(ARM) -#else -#define SUBTARGET_ARM -#endif - -#ifdef LLVM_COMPONENT_AARCH64 -#define SUBTARGET_AARCH64 SUBTARGET(AArch64) -#else -#define SUBTARGET_AARCH64 -#endif - -#ifdef LLVM_COMPONENT_AVR -#define SUBTARGET_AVR SUBTARGET(AVR) -#else -#define SUBTARGET_AVR -#endif - -#ifdef LLVM_COMPONENT_MIPS -#define SUBTARGET_MIPS SUBTARGET(Mips) -#else -#define SUBTARGET_MIPS -#endif - -#ifdef LLVM_COMPONENT_POWERPC -#define SUBTARGET_PPC SUBTARGET(PPC) -#else -#define SUBTARGET_PPC -#endif - -#ifdef LLVM_COMPONENT_SYSTEMZ -#define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ) -#else -#define SUBTARGET_SYSTEMZ -#endif - -#ifdef LLVM_COMPONENT_MSP430 -#define SUBTARGET_MSP430 SUBTARGET(MSP430) -#else -#define SUBTARGET_MSP430 -#endif - -#ifdef LLVM_COMPONENT_RISCV -#define SUBTARGET_RISCV SUBTARGET(RISCV) -#else -#define SUBTARGET_RISCV -#endif - -#ifdef LLVM_COMPONENT_SPARC -#define SUBTARGET_SPARC SUBTARGET(Sparc) -#else -#define SUBTARGET_SPARC -#endif - -#ifdef LLVM_COMPONENT_HEXAGON -#define SUBTARGET_HEXAGON SUBTARGET(Hexagon) -#else -#define SUBTARGET_HEXAGON -#endif - -#define GEN_SUBTARGETS \ - SUBTARGET_X86 \ - SUBTARGET_ARM \ - SUBTARGET_AARCH64 \ - SUBTARGET_AVR \ - SUBTARGET_MIPS \ - SUBTARGET_PPC \ - SUBTARGET_SYSTEMZ \ - SUBTARGET_MSP430 \ - SUBTARGET_SPARC \ - SUBTARGET_HEXAGON \ - SUBTARGET_RISCV \ - -#define SUBTARGET(x) \ - namespace llvm { \ - extern const SubtargetFeatureKV x##FeatureKV[]; \ - extern const SubtargetFeatureKV x##SubTypeKV[]; \ - } - -GEN_SUBTARGETS -#undef SUBTARGET - -extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, - const char *Feature) { - TargetMachine *Target = unwrap(TM); - const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - return MCInfo->checkFeatures(std::string("+") + Feature); -} - -enum class LLVMRustCodeModel { - Tiny, - Small, - Kernel, - Medium, - Large, - None, -}; - -static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) { - switch (Model) { - case LLVMRustCodeModel::Tiny: - return CodeModel::Tiny; - case LLVMRustCodeModel::Small: - return CodeModel::Small; - case LLVMRustCodeModel::Kernel: - return CodeModel::Kernel; - case LLVMRustCodeModel::Medium: - return CodeModel::Medium; - case LLVMRustCodeModel::Large: - return CodeModel::Large; - case LLVMRustCodeModel::None: - return None; - default: - report_fatal_error("Bad CodeModel."); - } -} - -enum class LLVMRustCodeGenOptLevel { - None, - Less, - Default, - Aggressive, -}; - -static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) { - switch (Level) { - case LLVMRustCodeGenOptLevel::None: - return CodeGenOpt::None; - case LLVMRustCodeGenOptLevel::Less: - return CodeGenOpt::Less; - case LLVMRustCodeGenOptLevel::Default: - return CodeGenOpt::Default; - case LLVMRustCodeGenOptLevel::Aggressive: - return CodeGenOpt::Aggressive; - default: - report_fatal_error("Bad CodeGenOptLevel."); - } -} - -enum class LLVMRustPassBuilderOptLevel { - O0, - O1, - O2, - O3, - Os, - Oz, -}; - -static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) { - switch (Level) { - case LLVMRustPassBuilderOptLevel::O0: - return PassBuilder::OptimizationLevel::O0; - case LLVMRustPassBuilderOptLevel::O1: - return PassBuilder::OptimizationLevel::O1; - case LLVMRustPassBuilderOptLevel::O2: - return PassBuilder::OptimizationLevel::O2; - case LLVMRustPassBuilderOptLevel::O3: - return PassBuilder::OptimizationLevel::O3; - case LLVMRustPassBuilderOptLevel::Os: - return PassBuilder::OptimizationLevel::Os; - case LLVMRustPassBuilderOptLevel::Oz: - return PassBuilder::OptimizationLevel::Oz; - default: - report_fatal_error("Bad PassBuilderOptLevel."); - } -} - -enum class LLVMRustRelocModel { - Static, - PIC, - DynamicNoPic, - ROPI, - RWPI, - ROPIRWPI, -}; - -static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) { - switch (RustReloc) { - case LLVMRustRelocModel::Static: - return Reloc::Static; - case LLVMRustRelocModel::PIC: - return Reloc::PIC_; - case LLVMRustRelocModel::DynamicNoPic: - return Reloc::DynamicNoPIC; - case LLVMRustRelocModel::ROPI: - return Reloc::ROPI; - case LLVMRustRelocModel::RWPI: - return Reloc::RWPI; - case LLVMRustRelocModel::ROPIRWPI: - return Reloc::ROPI_RWPI; - } - report_fatal_error("Bad RelocModel."); -} - -#ifdef LLVM_RUSTLLVM -/// getLongestEntryLength - Return the length of the longest entry in the table. -template<typename KV> -static size_t getLongestEntryLength(ArrayRef<KV> Table) { - size_t MaxLen = 0; - for (auto &I : Table) - MaxLen = std::max(MaxLen, std::strlen(I.Key)); - return MaxLen; -} - -extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { - const TargetMachine *Target = unwrap(TM); - const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch(); - const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); - const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable(); - unsigned MaxCPULen = getLongestEntryLength(CPUTable); - - printf("Available CPUs for this target:\n"); - if (HostArch == TargetArch) { - const StringRef HostCPU = sys::getHostCPUName(); - printf(" %-*s - Select the CPU of the current host (currently %.*s).\n", - MaxCPULen, "native", (int)HostCPU.size(), HostCPU.data()); - } - for (auto &CPU : CPUTable) - printf(" %-*s\n", MaxCPULen, CPU.Key); - printf("\n"); -} - -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { - const TargetMachine *Target = unwrap(TM); - const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable(); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable); - - printf("Available features for this target:\n"); - for (auto &Feature : FeatTable) - printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("\nRust-specific features:\n"); - printf(" %-*s - %s.\n", - MaxFeatLen, - "crt-static", - "Enables libraries with C Run-time Libraries(CRT) to be statically linked" - ); - printf("\n"); - - printf("Use +feature to enable a feature, or -feature to disable it.\n" - "For example, rustc -C -target-cpu=mycpu -C " - "target-feature=+feature1,-feature2\n\n"); -} - -#else - -extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) { - printf("Target CPU help is not supported by this LLVM version.\n\n"); -} - -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { - printf("Target features help is not supported by this LLVM version.\n\n"); -} -#endif - -extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { - StringRef Name = sys::getHostCPUName(); - *len = Name.size(); - return Name.data(); -} - -extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( - const char *TripleStr, const char *CPU, const char *Feature, - const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc, - LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, - bool FunctionSections, - bool DataSections, - bool TrapUnreachable, - bool Singlethread, - bool AsmComments, - bool EmitStackSizeSection, - bool RelaxELFRelocations, - bool UseInitArray) { - - auto OptLevel = fromRust(RustOptLevel); - auto RM = fromRust(RustReloc); - auto CM = fromRust(RustCM); - - std::string Error; - Triple Trip(Triple::normalize(TripleStr)); - const llvm::Target *TheTarget = - TargetRegistry::lookupTarget(Trip.getTriple(), Error); - if (TheTarget == nullptr) { - LLVMRustSetLastError(Error.c_str()); - return nullptr; - } - - TargetOptions Options; - - Options.FloatABIType = FloatABI::Default; - if (UseSoftFloat) { - Options.FloatABIType = FloatABI::Soft; - } - Options.DataSections = DataSections; - Options.FunctionSections = FunctionSections; - Options.MCOptions.AsmVerbose = AsmComments; - Options.MCOptions.PreserveAsmComments = AsmComments; - Options.MCOptions.ABIName = ABIStr; - Options.RelaxELFRelocations = RelaxELFRelocations; - Options.UseInitArray = UseInitArray; - - if (TrapUnreachable) { - // Tell LLVM to codegen `unreachable` into an explicit trap instruction. - // This limits the extent of possible undefined behavior in some cases, as - // it prevents control flow from "falling through" into whatever code - // happens to be laid out next in memory. - Options.TrapUnreachable = true; - } - - if (Singlethread) { - Options.ThreadModel = ThreadModel::Single; - } - - Options.EmitStackSizeSection = EmitStackSizeSection; - - TargetMachine *TM = TheTarget->createTargetMachine( - Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel); - return wrap(TM); -} - -extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { - delete unwrap(TM); -} - -extern "C" void LLVMRustConfigurePassManagerBuilder( - LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, - bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO, - const char* PGOGenPath, const char* PGOUsePath) { - unwrap(PMBR)->MergeFunctions = MergeFunctions; - unwrap(PMBR)->SLPVectorize = SLPVectorize; - unwrap(PMBR)->OptLevel = fromRust(OptLevel); - unwrap(PMBR)->LoopVectorize = LoopVectorize; - unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO; - - if (PGOGenPath) { - assert(!PGOUsePath); - unwrap(PMBR)->EnablePGOInstrGen = true; - unwrap(PMBR)->PGOInstrGen = PGOGenPath; - } - if (PGOUsePath) { - assert(!PGOGenPath); - unwrap(PMBR)->PGOInstrUse = PGOUsePath; - } -} - -// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` -// field of a PassManagerBuilder, we expose our own method of doing so. -extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR, - LLVMModuleRef M, - bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple); - if (DisableSimplifyLibCalls) - TLI->disableAllFunctions(); - unwrap(PMBR)->LibraryInfo = TLI; -} - -// Unfortunately, the LLVM C API doesn't provide a way to create the -// TargetLibraryInfo pass, so we use this method to do so. -extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, - bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl TLII(TargetTriple); - if (DisableSimplifyLibCalls) - TLII.disableAllFunctions(); - unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); -} - -// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over -// all the functions in a module, so we do that manually here. You'll find -// similar code in clang's BackendUtil.cpp file. -extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR, - LLVMModuleRef M) { - llvm::legacy::FunctionPassManager *P = - unwrap<llvm::legacy::FunctionPassManager>(PMR); - P->doInitialization(); - - // Upgrade all calls to old intrinsics first. - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;) - UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove - - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E; - ++I) - if (!I->isDeclaration()) - P->run(*I); - - P->doFinalization(); -} - -extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) { - // Initializing the command-line options more than once is not allowed. So, - // check if they've already been initialized. (This could happen if we're - // being called from rustpkg, for example). If the arguments change, then - // that's just kinda unfortunate. - static bool Initialized = false; - if (Initialized) - return; - Initialized = true; - cl::ParseCommandLineOptions(Argc, Argv); -} - -enum class LLVMRustFileType { - AssemblyFile, - ObjectFile, -}; - -#if LLVM_VERSION_GE(10, 0) -static CodeGenFileType fromRust(LLVMRustFileType Type) { - switch (Type) { - case LLVMRustFileType::AssemblyFile: - return CGFT_AssemblyFile; - case LLVMRustFileType::ObjectFile: - return CGFT_ObjectFile; - default: - report_fatal_error("Bad FileType."); - } -} -#else -static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) { - switch (Type) { - case LLVMRustFileType::AssemblyFile: - return TargetMachine::CGFT_AssemblyFile; - case LLVMRustFileType::ObjectFile: - return TargetMachine::CGFT_ObjectFile; - default: - report_fatal_error("Bad FileType."); - } -} -#endif - -extern "C" LLVMRustResult -LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, - LLVMModuleRef M, const char *Path, - LLVMRustFileType RustFileType) { - llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR); - auto FileType = fromRust(RustFileType); - - std::string ErrorInfo; - std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::F_None); - if (EC) - ErrorInfo = EC.message(); - if (ErrorInfo != "") { - LLVMRustSetLastError(ErrorInfo.c_str()); - return LLVMRustResult::Failure; - } - - buffer_ostream BOS(OS); - unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false); - PM->run(*unwrap(M)); - - // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output - // stream (OS), so the only real safe place to delete this is here? Don't we - // wish this was written in Rust? - LLVMDisposePassManager(PMR); - return LLVMRustResult::Success; -} - -extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler - const char*, // pass name - const char*); // IR name -extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler - -#if LLVM_VERSION_GE(9, 0) - -std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { - if (any_isa<const Module *>(WrappedIr)) - return any_cast<const Module *>(WrappedIr)->getName().str(); - if (any_isa<const Function *>(WrappedIr)) - return any_cast<const Function *>(WrappedIr)->getName().str(); - if (any_isa<const Loop *>(WrappedIr)) - return any_cast<const Loop *>(WrappedIr)->getName().str(); - if (any_isa<const LazyCallGraph::SCC *>(WrappedIr)) - return any_cast<const LazyCallGraph::SCC *>(WrappedIr)->getName(); - return "<UNKNOWN>"; -} - - -void LLVMSelfProfileInitializeCallbacks( - PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler, - LLVMRustSelfProfileBeforePassCallback BeforePassCallback, - LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { - PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback]( - StringRef Pass, llvm::Any Ir) { - std::string PassName = Pass.str(); - std::string IrName = LLVMRustwrappedIrGetName(Ir); - BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); - return true; - }); - - PIC.registerAfterPassCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { - AfterPassCallback(LlvmSelfProfiler); - }); - - PIC.registerAfterPassInvalidatedCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) { - AfterPassCallback(LlvmSelfProfiler); - }); - - PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback]( - StringRef Pass, llvm::Any Ir) { - std::string PassName = Pass.str(); - std::string IrName = LLVMRustwrappedIrGetName(Ir); - BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); - }); - - PIC.registerAfterAnalysisCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { - AfterPassCallback(LlvmSelfProfiler); - }); -} -#endif - -enum class LLVMRustOptStage { - PreLinkNoLTO, - PreLinkThinLTO, - PreLinkFatLTO, - ThinLTO, - FatLTO, -}; - -struct LLVMRustSanitizerOptions { - bool SanitizeAddress; - bool SanitizeAddressRecover; - bool SanitizeMemory; - bool SanitizeMemoryRecover; - int SanitizeMemoryTrackOrigins; - bool SanitizeThread; -}; - -extern "C" void -LLVMRustOptimizeWithNewPassManager( - LLVMModuleRef ModuleRef, - LLVMTargetMachineRef TMRef, - LLVMRustPassBuilderOptLevel OptLevelRust, - LLVMRustOptStage OptStage, - bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers, - bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, - bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, - LLVMRustSanitizerOptions *SanitizerOptions, - const char *PGOGenPath, const char *PGOUsePath, - void* LlvmSelfProfiler, - LLVMRustSelfProfileBeforePassCallback BeforePassCallback, - LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { -#if LLVM_VERSION_GE(9, 0) - Module *TheModule = unwrap(ModuleRef); - TargetMachine *TM = unwrap(TMRef); - PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust); - - // FIXME: MergeFunctions is not supported by NewPM yet. - (void) MergeFunctions; - - PipelineTuningOptions PTO; - PTO.LoopUnrolling = UnrollLoops; - PTO.LoopInterleaving = UnrollLoops; - PTO.LoopVectorization = LoopVectorize; - PTO.SLPVectorization = SLPVectorize; - - PassInstrumentationCallbacks PIC; - StandardInstrumentations SI; - SI.registerCallbacks(PIC); - - if (LlvmSelfProfiler){ - LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); - } - - Optional<PGOOptions> PGOOpt; - if (PGOGenPath) { - assert(!PGOUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr); - } else if (PGOUsePath) { - assert(!PGOGenPath); - PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse); - } - - PassBuilder PB(TM, PTO, PGOOpt, &PIC); - - // FIXME: We may want to expose this as an option. - bool DebugPassManager = false; - LoopAnalysisManager LAM(DebugPassManager); - FunctionAnalysisManager FAM(DebugPassManager); - CGSCCAnalysisManager CGAM(DebugPassManager); - ModuleAnalysisManager MAM(DebugPassManager); - - FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); - - Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple)); - if (DisableSimplifyLibCalls) - TLII->disableAllFunctions(); - FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); - - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - - // We manually collect pipeline callbacks so we can apply them at O0, where the - // PassBuilder does not create a pipeline. - std::vector<std::function<void(ModulePassManager &)>> PipelineStartEPCallbacks; -#if LLVM_VERSION_GE(11, 0) - std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>> - OptimizerLastEPCallbacks; -#else - std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>> - OptimizerLastEPCallbacks; -#endif - - if (VerifyIR) { - PipelineStartEPCallbacks.push_back([VerifyIR](ModulePassManager &MPM) { - MPM.addPass(VerifierPass()); - }); - } - - if (SanitizerOptions) { - if (SanitizerOptions->SanitizeMemory) { - MemorySanitizerOptions Options( - SanitizerOptions->SanitizeMemoryTrackOrigins, - SanitizerOptions->SanitizeMemoryRecover, - /*CompileKernel=*/false); -#if LLVM_VERSION_GE(11, 0) - OptimizerLastEPCallbacks.push_back( - [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { - MPM.addPass(MemorySanitizerPass(Options)); - MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); - } - ); -#else -#if LLVM_VERSION_GE(10, 0) - PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) { - MPM.addPass(MemorySanitizerPass(Options)); - }); -#endif - OptimizerLastEPCallbacks.push_back( - [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(MemorySanitizerPass(Options)); - } - ); -#endif - } - - if (SanitizerOptions->SanitizeThread) { -#if LLVM_VERSION_GE(11, 0) - OptimizerLastEPCallbacks.push_back( - [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { - MPM.addPass(ThreadSanitizerPass()); - MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); - } - ); -#else -#if LLVM_VERSION_GE(10, 0) - PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM) { - MPM.addPass(ThreadSanitizerPass()); - }); -#endif - OptimizerLastEPCallbacks.push_back( - [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(ThreadSanitizerPass()); - } - ); -#endif - } - - if (SanitizerOptions->SanitizeAddress) { -#if LLVM_VERSION_GE(11, 0) - OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { - MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true))); - } - ); -#else - PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) { - MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); - }); - OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true)); - } - ); - PipelineStartEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM) { - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); - } - ); -#endif - } - } - - ModulePassManager MPM(DebugPassManager); - if (!NoPrepopulatePasses) { - if (OptLevel == PassBuilder::OptimizationLevel::O0) { - for (const auto &C : PipelineStartEPCallbacks) - C(MPM); - -#if LLVM_VERSION_GE(11, 0) - for (const auto &C : OptimizerLastEPCallbacks) - C(MPM, OptLevel); -#else - if (!OptimizerLastEPCallbacks.empty()) { - FunctionPassManager FPM(DebugPassManager); - for (const auto &C : OptimizerLastEPCallbacks) - C(FPM, OptLevel); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - } -#endif - - MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); - -#if LLVM_VERSION_GE(10, 0) - if (PGOOpt) { - PB.addPGOInstrPassesForO0( - MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, - /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); - } -#endif - } else { - for (const auto &C : PipelineStartEPCallbacks) - PB.registerPipelineStartEPCallback(C); - if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { - for (const auto &C : OptimizerLastEPCallbacks) - PB.registerOptimizerLastEPCallback(C); - } - - switch (OptStage) { - case LLVMRustOptStage::PreLinkNoLTO: - MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager); - break; - case LLVMRustOptStage::PreLinkThinLTO: - MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); -#if LLVM_VERSION_GE(11, 0) - for (const auto &C : OptimizerLastEPCallbacks) - C(MPM, OptLevel); -#else - if (!OptimizerLastEPCallbacks.empty()) { - FunctionPassManager FPM(DebugPassManager); - for (const auto &C : OptimizerLastEPCallbacks) - C(FPM, OptLevel); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - } -#endif - break; - case LLVMRustOptStage::PreLinkFatLTO: - MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); - break; - case LLVMRustOptStage::ThinLTO: - // FIXME: Does it make sense to pass the ModuleSummaryIndex? - // It only seems to be needed for C++ specific optimizations. - MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); - break; - case LLVMRustOptStage::FatLTO: - MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); - break; - } - } - } - - if (UseThinLTOBuffers) { - MPM.addPass(CanonicalizeAliasesPass()); - MPM.addPass(NameAnonGlobalPass()); - } - - // Upgrade all calls to old intrinsics first. - for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;) - UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove - - MPM.run(*TheModule, MAM); -#else - // The new pass manager has been available for a long time, - // but we don't bother supporting it on old LLVM versions. - report_fatal_error("New pass manager only supported since LLVM 9"); -#endif -} - -// Callback to demangle function name -// Parameters: -// * name to be demangled -// * name len -// * output buffer -// * output buffer len -// Returns len of demangled string, or 0 if demangle failed. -typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t); - - -namespace { - -class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter { - DemangleFn Demangle; - std::vector<char> Buf; - -public: - RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {} - - // Return empty string if demangle failed - // or if name does not need to be demangled - StringRef CallDemangle(StringRef name) { - if (!Demangle) { - return StringRef(); - } - - if (Buf.size() < name.size() * 2) { - // Semangled name usually shorter than mangled, - // but allocate twice as much memory just in case - Buf.resize(name.size() * 2); - } - - auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size()); - if (!R) { - // Demangle failed. - return StringRef(); - } - - auto Demangled = StringRef(Buf.data(), R); - if (Demangled == name) { - // Do not print anything if demangled name is equal to mangled. - return StringRef(); - } - - return Demangled; - } - - void emitFunctionAnnot(const Function *F, - formatted_raw_ostream &OS) override { - StringRef Demangled = CallDemangle(F->getName()); - if (Demangled.empty()) { - return; - } - - OS << "; " << Demangled << "\n"; - } - - void emitInstructionAnnot(const Instruction *I, - formatted_raw_ostream &OS) override { - const char *Name; - const Value *Value; - if (const CallInst *CI = dyn_cast<CallInst>(I)) { - Name = "call"; - Value = CI->getCalledOperand(); - } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) { - Name = "invoke"; - Value = II->getCalledOperand(); - } else { - // Could demangle more operations, e. g. - // `store %place, @function`. - return; - } - - if (!Value->hasName()) { - return; - } - - StringRef Demangled = CallDemangle(Value->getName()); - if (Demangled.empty()) { - return; - } - - OS << "; " << Name << " " << Demangled << "\n"; - } -}; - -} // namespace - -extern "C" LLVMRustResult -LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { - std::string ErrorInfo; - std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::F_None); - if (EC) - ErrorInfo = EC.message(); - if (ErrorInfo != "") { - LLVMRustSetLastError(ErrorInfo.c_str()); - return LLVMRustResult::Failure; - } - - RustAssemblyAnnotationWriter AAW(Demangle); - formatted_raw_ostream FOS(OS); - unwrap(M)->print(FOS, &AAW); - - return LLVMRustResult::Success; -} - -extern "C" void LLVMRustPrintPasses() { - LLVMInitializePasses(); - struct MyListener : PassRegistrationListener { - void passEnumerate(const PassInfo *Info) { - StringRef PassArg = Info->getPassArgument(); - StringRef PassName = Info->getPassName(); - if (!PassArg.empty()) { - // These unsigned->signed casts could theoretically overflow, but - // realistically never will (and even if, the result is implementation - // defined rather plain UB). - printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(), - (int)PassName.size(), PassName.data()); - } - } - } Listener; - - PassRegistry *PR = PassRegistry::getPassRegistry(); - PR->enumerateWith(&Listener); -} - -extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR, - bool AddLifetimes) { - unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes); -} - -extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, - size_t Len) { - llvm::legacy::PassManager passes; - - auto PreserveFunctions = [=](const GlobalValue &GV) { - for (size_t I = 0; I < Len; I++) { - if (GV.getName() == Symbols[I]) { - return true; - } - } - return false; - }; - - passes.add(llvm::createInternalizePass(PreserveFunctions)); - - passes.run(*unwrap(M)); -} - -extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) { - for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E; - ++GV) { - GV->setDoesNotThrow(); - Function *F = dyn_cast<Function>(GV); - if (F == nullptr) - continue; - - for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) { - if (isa<InvokeInst>(I)) { - InvokeInst *CI = cast<InvokeInst>(I); - CI->setDoesNotThrow(); - } - } - } - } -} - -extern "C" void -LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module, - LLVMTargetMachineRef TMR) { - TargetMachine *Target = unwrap(TMR); - unwrap(Module)->setDataLayout(Target->createDataLayout()); -} - -extern "C" void LLVMRustSetModulePICLevel(LLVMModuleRef M) { - unwrap(M)->setPICLevel(PICLevel::Level::BigPIC); -} - -extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) { - unwrap(M)->setPIELevel(PIELevel::Level::Large); -} - -// Here you'll find an implementation of ThinLTO as used by the Rust compiler -// right now. This ThinLTO support is only enabled on "recent ish" versions of -// LLVM, and otherwise it's just blanket rejected from other compilers. -// -// Most of this implementation is straight copied from LLVM. At the time of -// this writing it wasn't *quite* suitable to reuse more code from upstream -// for our purposes, but we should strive to upstream this support once it's -// ready to go! I figure we may want a bit of testing locally first before -// sending this upstream to LLVM. I hear though they're quite eager to receive -// feedback like this! -// -// If you're reading this code and wondering "what in the world" or you're -// working "good lord by LLVM upgrade is *still* failing due to these bindings" -// then fear not! (ok maybe fear a little). All code here is mostly based -// on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM. -// -// You'll find that the general layout here roughly corresponds to the `run` -// method in that file as well as `ProcessThinLTOModule`. Functions are -// specifically commented below as well, but if you're updating this code -// or otherwise trying to understand it, the LLVM source will be useful in -// interpreting the mysteries within. -// -// Otherwise I'll apologize in advance, it probably requires a relatively -// significant investment on your part to "truly understand" what's going on -// here. Not saying I do myself, but it took me awhile staring at LLVM's source -// and various online resources about ThinLTO to make heads or tails of all -// this. - -// This is a shared data structure which *must* be threadsafe to share -// read-only amongst threads. This also corresponds basically to the arguments -// of the `ProcessThinLTOModule` function in the LLVM source. -struct LLVMRustThinLTOData { - // The combined index that is the global analysis over all modules we're - // performing ThinLTO for. This is mostly managed by LLVM. - ModuleSummaryIndex Index; - - // All modules we may look at, stored as in-memory serialized versions. This - // is later used when inlining to ensure we can extract any module to inline - // from. - StringMap<MemoryBufferRef> ModuleMap; - - // A set that we manage of everything we *don't* want internalized. Note that - // this includes all transitive references right now as well, but it may not - // always! - DenseSet<GlobalValue::GUID> GUIDPreservedSymbols; - - // Not 100% sure what these are, but they impact what's internalized and - // what's inlined across modules, I believe. - StringMap<FunctionImporter::ImportMapTy> ImportLists; - StringMap<FunctionImporter::ExportSetTy> ExportLists; - StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries; - - LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {} -}; - -// Just an argument to the `LLVMRustCreateThinLTOData` function below. -struct LLVMRustThinLTOModule { - const char *identifier; - const char *data; - size_t len; -}; - -// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it -// does. -static const GlobalValueSummary * -getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) { - auto StrongDefForLinker = llvm::find_if( - GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) { - auto Linkage = Summary->linkage(); - return !GlobalValue::isAvailableExternallyLinkage(Linkage) && - !GlobalValue::isWeakForLinker(Linkage); - }); - if (StrongDefForLinker != GVSummaryList.end()) - return StrongDefForLinker->get(); - - auto FirstDefForLinker = llvm::find_if( - GVSummaryList, [](const std::unique_ptr<GlobalValueSummary> &Summary) { - auto Linkage = Summary->linkage(); - return !GlobalValue::isAvailableExternallyLinkage(Linkage); - }); - if (FirstDefForLinker == GVSummaryList.end()) - return nullptr; - return FirstDefForLinker->get(); -} - -// The main entry point for creating the global ThinLTO analysis. The structure -// here is basically the same as before threads are spawned in the `run` -// function of `lib/LTO/ThinLTOCodeGenerator.cpp`. -extern "C" LLVMRustThinLTOData* -LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, - int num_modules, - const char **preserved_symbols, - int num_symbols) { -#if LLVM_VERSION_GE(10, 0) - auto Ret = std::make_unique<LLVMRustThinLTOData>(); -#else - auto Ret = llvm::make_unique<LLVMRustThinLTOData>(); -#endif - - // Load each module's summary and merge it into one combined index - for (int i = 0; i < num_modules; i++) { - auto module = &modules[i]; - StringRef buffer(module->data, module->len); - MemoryBufferRef mem_buffer(buffer, module->identifier); - - Ret->ModuleMap[module->identifier] = mem_buffer; - - if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) { - LLVMRustSetLastError(toString(std::move(Err)).c_str()); - return nullptr; - } - } - - // Collect for each module the list of function it defines (GUID -> Summary) - Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries); - - // Convert the preserved symbols set from string to GUID, this is then needed - // for internalization. - for (int i = 0; i < num_symbols; i++) { - auto GUID = GlobalValue::getGUID(preserved_symbols[i]); - Ret->GUIDPreservedSymbols.insert(GUID); - } - - // Collect the import/export lists for all modules from the call-graph in the - // combined index - // - // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` - auto deadIsPrevailing = [&](GlobalValue::GUID G) { - return PrevailingType::Unknown; - }; - // We don't have a complete picture in our use of ThinLTO, just our immediate - // crate, so we need `ImportEnabled = false` to limit internalization. - // Otherwise, we sometimes lose `static` values -- see #60184. - computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols, - deadIsPrevailing, /* ImportEnabled = */ false); - ComputeCrossModuleImport( - Ret->Index, - Ret->ModuleToDefinedGVSummaries, - Ret->ImportLists, - Ret->ExportLists - ); - - // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it - // impacts the caching. - // - // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this - // being lifted from `lib/LTO/LTO.cpp` as well - StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR; - DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy; - for (auto &I : Ret->Index) { - if (I.second.SummaryList.size() > 1) - PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList); - } - auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { - const auto &Prevailing = PrevailingCopy.find(GUID); - if (Prevailing == PrevailingCopy.end()) - return true; - return Prevailing->second == S; - }; - auto recordNewLinkage = [&](StringRef ModuleIdentifier, - GlobalValue::GUID GUID, - GlobalValue::LinkageTypes NewLinkage) { - ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; - }; -#if LLVM_VERSION_GE(9, 0) - thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage, - Ret->GUIDPreservedSymbols); -#else - thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage); -#endif - - // Here we calculate an `ExportedGUIDs` set for use in the `isExported` - // callback below. This callback below will dictate the linkage for all - // summaries in the index, and we basically just only want to ensure that dead - // symbols are internalized. Otherwise everything that's already external - // linkage will stay as external, and internal will stay as internal. - std::set<GlobalValue::GUID> ExportedGUIDs; - for (auto &List : Ret->Index) { - for (auto &GVS: List.second.SummaryList) { - if (GlobalValue::isLocalLinkage(GVS->linkage())) - continue; - auto GUID = GVS->getOriginalName(); - if (GVS->flags().Live) - ExportedGUIDs.insert(GUID); - } - } -#if LLVM_VERSION_GE(10, 0) - auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { - const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); - return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(VI)) || - ExportedGUIDs.count(VI.getGUID()); - }; - thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); -#else - auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { - const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); - return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(GUID)) || - ExportedGUIDs.count(GUID); - }; - thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); -#endif - - return Ret.release(); -} - -extern "C" void -LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { - delete Data; -} - -// Below are the various passes that happen *per module* when doing ThinLTO. -// -// In other words, these are the functions that are all run concurrently -// with one another, one per module. The passes here correspond to the analysis -// passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the -// `ProcessThinLTOModule` function. Here they're split up into separate steps -// so rustc can save off the intermediate bytecode between each step. - -#if LLVM_VERSION_GE(11, 0) -static bool -clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { - // When linking an ELF shared object, dso_local should be dropped. We - // conservatively do this for -fpic. - bool ClearDSOLocalOnDeclarations = - TM.getTargetTriple().isOSBinFormatELF() && - TM.getRelocationModel() != Reloc::Static && - Mod.getPIELevel() == PIELevel::Default; - return ClearDSOLocalOnDeclarations; -} -#endif - -extern "C" bool -LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, - LLVMTargetMachineRef TM) { - Module &Mod = *unwrap(M); - TargetMachine &Target = *unwrap(TM); - -#if LLVM_VERSION_GE(11, 0) - bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); - bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal); -#else - bool error = renameModuleForThinLTO(Mod, Data->Index); -#endif - - if (error) { - LLVMRustSetLastError("renameModuleForThinLTO failed"); - return false; - } - return true; -} - -extern "C" bool -LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { - Module &Mod = *unwrap(M); - const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); - thinLTOResolvePrevailingInModule(Mod, DefinedGlobals); - return true; -} - -extern "C" bool -LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { - Module &Mod = *unwrap(M); - const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); - thinLTOInternalizeModule(Mod, DefinedGlobals); - return true; -} - -extern "C" bool -LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, - LLVMTargetMachineRef TM) { - Module &Mod = *unwrap(M); - TargetMachine &Target = *unwrap(TM); - - const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier()); - auto Loader = [&](StringRef Identifier) { - const auto &Memory = Data->ModuleMap.lookup(Identifier); - auto &Context = Mod.getContext(); - auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true); - - if (!MOrErr) - return MOrErr; - - // The rest of this closure is a workaround for - // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports - // we accidentally import wasm custom sections into different modules, - // duplicating them by in the final output artifact. - // - // The issue is worked around here by manually removing the - // `wasm.custom_sections` named metadata node from any imported module. This - // we know isn't used by any optimization pass so there's no need for it to - // be imported. - // - // Note that the metadata is currently lazily loaded, so we materialize it - // here before looking up if there's metadata inside. The `FunctionImporter` - // will immediately materialize metadata anyway after an import, so this - // shouldn't be a perf hit. - if (Error Err = (*MOrErr)->materializeMetadata()) { - Expected<std::unique_ptr<Module>> Ret(std::move(Err)); - return Ret; - } - - auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections"); - if (WasmCustomSections) - WasmCustomSections->eraseFromParent(); - - return MOrErr; - }; -#if LLVM_VERSION_GE(11, 0) - bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); - FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal); -#else - FunctionImporter Importer(Data->Index, Loader); -#endif - Expected<bool> Result = Importer.importFunctions(Mod, ImportList); - if (!Result) { - LLVMRustSetLastError(toString(Result.takeError()).c_str()); - return false; - } - return true; -} - -extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload - const char*, // importing module name - const char*); // imported module name - -// Calls `module_name_callback` for each module import done by ThinLTO. -// The callback is provided with regular null-terminated C strings. -extern "C" void -LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *data, - LLVMRustModuleNameCallback module_name_callback, - void* callback_payload) { - for (const auto& importing_module : data->ImportLists) { - const std::string importing_module_id = importing_module.getKey().str(); - const auto& imports = importing_module.getValue(); - for (const auto& imported_module : imports) { - const std::string imported_module_id = imported_module.getKey().str(); - module_name_callback(callback_payload, - importing_module_id.c_str(), - imported_module_id.c_str()); - } - } -} - -// This struct and various functions are sort of a hack right now, but the -// problem is that we've got in-memory LLVM modules after we generate and -// optimize all codegen-units for one compilation in rustc. To be compatible -// with the LTO support above we need to serialize the modules plus their -// ThinLTO summary into memory. -// -// This structure is basically an owned version of a serialize module, with -// a ThinLTO summary attached. -struct LLVMRustThinLTOBuffer { - std::string data; -}; - -extern "C" LLVMRustThinLTOBuffer* -LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) - auto Ret = std::make_unique<LLVMRustThinLTOBuffer>(); -#else - auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>(); -#endif - { - raw_string_ostream OS(Ret->data); - { - legacy::PassManager PM; - PM.add(createWriteThinLTOBitcodePass(OS)); - PM.run(*unwrap(M)); - } - } - return Ret.release(); -} - -extern "C" void -LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) { - delete Buffer; -} - -extern "C" const void* -LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) { - return Buffer->data.data(); -} - -extern "C" size_t -LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { - return Buffer->data.length(); -} - -// This is what we used to parse upstream bitcode for actual ThinLTO -// processing. We'll call this once per module optimized through ThinLTO, and -// it'll be called concurrently on many threads. -extern "C" LLVMModuleRef -LLVMRustParseBitcodeForLTO(LLVMContextRef Context, - const char *data, - size_t len, - const char *identifier) { - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, identifier); - unwrap(Context)->enableDebugTypeODRUniquing(); - Expected<std::unique_ptr<Module>> SrcOrError = - parseBitcodeFile(Buffer, *unwrap(Context)); - if (!SrcOrError) { - LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str()); - return nullptr; - } - return wrap(std::move(*SrcOrError).release()); -} - -// Find the bitcode section in the object file data and return it as a slice. -// Fail if the bitcode section is present but empty. -// -// On success, the return value is the pointer to the start of the slice and -// `out_len` is filled with the (non-zero) length. On failure, the return value -// is `nullptr` and `out_len` is set to zero. -extern "C" const char* -LLVMRustGetBitcodeSliceFromObjectData(const char *data, - size_t len, - size_t *out_len) { - *out_len = 0; - - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, ""); // The id is unused. - - Expected<MemoryBufferRef> BitcodeOrError = - object::IRObjectFile::findBitcodeInMemBuffer(Buffer); - if (!BitcodeOrError) { - LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str()); - return nullptr; - } - - *out_len = BitcodeOrError->getBufferSize(); - return BitcodeOrError->getBufferStart(); -} - -// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See -// the comment in `back/lto.rs` for why this exists. -extern "C" void -LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, - DICompileUnit **A, - DICompileUnit **B) { - Module *M = unwrap(Mod); - DICompileUnit **Cur = A; - DICompileUnit **Next = B; - for (DICompileUnit *CU : M->debug_compile_units()) { - *Cur = CU; - Cur = Next; - Next = nullptr; - if (Cur == nullptr) - break; - } -} - -// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See -// the comment in `back/lto.rs` for why this exists. -extern "C" void -LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { - Module *M = unwrap(Mod); - - // If the original source module didn't have a `DICompileUnit` then try to - // merge all the existing compile units. If there aren't actually any though - // then there's not much for us to do so return. - if (Unit == nullptr) { - for (DICompileUnit *CU : M->debug_compile_units()) { - Unit = CU; - break; - } - if (Unit == nullptr) - return; - } - - // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and - // process it recursively. Note that we used to specifically iterate over - // instructions to ensure we feed everything into it, but `processModule` - // started doing this the same way in LLVM 7 (commit d769eb36ab2b8). - DebugInfoFinder Finder; - Finder.processModule(*M); - - // After we've found all our debuginfo, rewrite all subprograms to point to - // the same `DICompileUnit`. - for (auto &F : Finder.subprograms()) { - F->replaceUnit(Unit); - } - - // Erase any other references to other `DICompileUnit` instances, the verifier - // will later ensure that we don't actually have any other stale references to - // worry about. - auto *MD = M->getNamedMetadata("llvm.dbg.cu"); - MD->clearOperands(); - MD->addOperand(Unit); -} diff --git a/src/rustllvm/README b/src/rustllvm/README deleted file mode 100644 index e1c6dd07d2b..00000000000 --- a/src/rustllvm/README +++ /dev/null @@ -1,16 +0,0 @@ -This directory currently contains some LLVM support code. This will generally -be sent upstream to LLVM in time; for now it lives here. - -NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never* -be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types -must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here. - -Functions that return a failure status and leave the error in -the LLVM last error should return an LLVMRustResult rather than an -int or anything to avoid confusion. - -When translating enums, add a single `Other` variant as the first -one to allow for new variants to be added. It should abort when used -as an input. - -All other types must not be typedef-ed as such. diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp deleted file mode 100644 index 9d90b0dfe07..00000000000 --- a/src/rustllvm/RustWrapper.cpp +++ /dev/null @@ -1,1721 +0,0 @@ -#include "rustllvm.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Object/Archive.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" -#include "llvm/Support/Signals.h" -#include "llvm/ADT/Optional.h" - -#include <iostream> - -//===----------------------------------------------------------------------=== -// -// 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; - -// LLVMAtomicOrdering is already an enum - don't create another -// one. -static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) { - switch (Ordering) { - case LLVMAtomicOrderingNotAtomic: - return AtomicOrdering::NotAtomic; - case LLVMAtomicOrderingUnordered: - return AtomicOrdering::Unordered; - case LLVMAtomicOrderingMonotonic: - return AtomicOrdering::Monotonic; - case LLVMAtomicOrderingAcquire: - return AtomicOrdering::Acquire; - case LLVMAtomicOrderingRelease: - return AtomicOrdering::Release; - case LLVMAtomicOrderingAcquireRelease: - return AtomicOrdering::AcquireRelease; - case LLVMAtomicOrderingSequentiallyConsistent: - return AtomicOrdering::SequentiallyConsistent; - } - - report_fatal_error("Invalid LLVMAtomicOrdering value!"); -} - -static LLVM_THREAD_LOCAL char *LastError; - -// Custom error handler for fatal LLVM errors. -// -// Notably it exits the process with code 101, unlike LLVM's default of 1. -static void FatalErrorHandler(void *UserData, - const std::string& Reason, - bool GenCrashDiag) { - // Do the same thing that the default error handler does. - std::cerr << "LLVM ERROR: " << Reason << std::endl; - - // Since this error handler exits the process, we have to run any cleanup that - // LLVM would run after handling the error. This might change with an LLVM - // upgrade. - sys::RunInterruptHandlers(); - - exit(101); -} - -extern "C" void LLVMRustInstallFatalErrorHandler() { - install_fatal_error_handler(FatalErrorHandler); -} - -extern "C" LLVMMemoryBufferRef -LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr = - MemoryBuffer::getFile(Path, -1, false); - if (!BufOr) { - LLVMRustSetLastError(BufOr.getError().message().c_str()); - return nullptr; - } - return wrap(BufOr.get().release()); -} - -extern "C" char *LLVMRustGetLastError(void) { - char *Ret = LastError; - LastError = nullptr; - return Ret; -} - -extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) { - return unwrap(M)->getInstructionCount(); -} - -extern "C" void LLVMRustSetLastError(const char *Err) { - free((void *)LastError); - LastError = strdup(Err); -} - -extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) { - auto ctx = new LLVMContext(); - ctx->setDiscardValueNames(shouldDiscardNames); - return wrap(ctx); -} - -extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, - const char *Triple) { - unwrap(M)->setTargetTriple(Triple::normalize(Triple)); -} - -extern "C" void LLVMRustPrintPassTimings() { - raw_fd_ostream OS(2, false); // stderr. - TimerGroup::printAll(OS); -} - -extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, - size_t NameLen) { - return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen))); -} - -extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, - const char *Name, - size_t NameLen, - LLVMTypeRef FunctionTy) { - return wrap(unwrap(M) - ->getOrInsertFunction(StringRef(Name, NameLen), - unwrap<FunctionType>(FunctionTy)) -#if LLVM_VERSION_GE(9, 0) - .getCallee() -#endif - ); -} - -extern "C" LLVMValueRef -LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { - StringRef NameRef(Name, NameLen); - return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty))); -} - -extern "C" LLVMValueRef -LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { - return wrap(new GlobalVariable(*unwrap(M), - unwrap(Ty), - false, - GlobalValue::PrivateLinkage, - nullptr)); -} - -extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) { - return wrap(Type::getMetadataTy(*unwrap(C))); -} - -static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { - switch (Kind) { - case AlwaysInline: - return Attribute::AlwaysInline; - case ByVal: - return Attribute::ByVal; - case Cold: - return Attribute::Cold; - case InlineHint: - return Attribute::InlineHint; - case MinSize: - return Attribute::MinSize; - case Naked: - return Attribute::Naked; - case NoAlias: - return Attribute::NoAlias; - case NoCapture: - return Attribute::NoCapture; - case NoInline: - return Attribute::NoInline; - case NonNull: - return Attribute::NonNull; - case NoRedZone: - return Attribute::NoRedZone; - case NoReturn: - return Attribute::NoReturn; - case NoUnwind: - return Attribute::NoUnwind; - case OptimizeForSize: - return Attribute::OptimizeForSize; - case ReadOnly: - return Attribute::ReadOnly; - case SExt: - return Attribute::SExt; - case StructRet: - return Attribute::StructRet; - case UWTable: - return Attribute::UWTable; - case ZExt: - return Attribute::ZExt; - case InReg: - return Attribute::InReg; - case SanitizeThread: - return Attribute::SanitizeThread; - case SanitizeAddress: - return Attribute::SanitizeAddress; - case SanitizeMemory: - return Attribute::SanitizeMemory; - case NonLazyBind: - return Attribute::NonLazyBind; - case OptimizeNone: - return Attribute::OptimizeNone; - case ReturnsTwice: - return Attribute::ReturnsTwice; - case ReadNone: - return Attribute::ReadNone; - case InaccessibleMemOnly: - return Attribute::InaccessibleMemOnly; - } - report_fatal_error("bad AttributeKind"); -} - -extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index, - LLVMRustAttribute RustAttr) { - CallBase *Call = unwrap<CallBase>(Instr); - Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr)); - Call->addAttribute(Index, Attr); -} - -extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr, - unsigned Index, - uint32_t Bytes) { - CallBase *Call = unwrap<CallBase>(Instr); - AttrBuilder B; - B.addAlignmentAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); -} - -extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, - unsigned Index, - uint64_t Bytes) { - CallBase *Call = unwrap<CallBase>(Instr); - AttrBuilder B; - B.addDereferenceableAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); -} - -extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr, - unsigned Index, - uint64_t Bytes) { - CallBase *Call = unwrap<CallBase>(Instr); - AttrBuilder B; - B.addDereferenceableOrNullAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); -} - -extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index, - LLVMTypeRef Ty) { - CallBase *Call = unwrap<CallBase>(Instr); -#if LLVM_VERSION_GE(9, 0) - Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty)); -#else - Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal); -#endif - Call->addAttribute(Index, Attr); -} - -extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, - LLVMRustAttribute RustAttr) { - Function *A = unwrap<Function>(Fn); - Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr)); - AttrBuilder B(Attr); - A->addAttributes(Index, B); -} - -extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn, - unsigned Index, - uint32_t Bytes) { - Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addAlignmentAttr(Bytes); - A->addAttributes(Index, B); -} - -extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index, - uint64_t Bytes) { - Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addDereferenceableAttr(Bytes); - A->addAttributes(Index, B); -} - -extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn, - unsigned Index, - uint64_t Bytes) { - Function *A = unwrap<Function>(Fn); - AttrBuilder B; - B.addDereferenceableOrNullAttr(Bytes); - A->addAttributes(Index, B); -} - -extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, - LLVMTypeRef Ty) { - Function *F = unwrap<Function>(Fn); -#if LLVM_VERSION_GE(9, 0) - Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty)); -#else - Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal); -#endif - F->addAttribute(Index, Attr); -} - -extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, - unsigned Index, - const char *Name, - const char *Value) { - Function *F = unwrap<Function>(Fn); - AttrBuilder B; - B.addAttribute(Name, Value); - F->addAttributes(Index, B); -} - -extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, - unsigned Index, - LLVMRustAttribute RustAttr) { - Function *F = unwrap<Function>(Fn); - Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr)); - AttrBuilder B(Attr); - auto PAL = F->getAttributes(); - auto PALNew = PAL.removeAttributes(F->getContext(), Index, B); - F->setAttributes(PALNew); -} - -// enable fpmath flag UnsafeAlgebra -extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { - if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) { - I->setFast(true); - } -} - -extern "C" LLVMValueRef -LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name, - LLVMAtomicOrdering Order) { - Value *Ptr = unwrap(Source); - Type *Ty = Ptr->getType()->getPointerElementType(); - LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name); - LI->setAtomic(fromRust(Order)); - return wrap(LI); -} - -extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B, - LLVMValueRef V, - LLVMValueRef Target, - LLVMAtomicOrdering Order) { - StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target)); - SI->setAtomic(fromRust(Order)); - return wrap(SI); -} - -// FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak -// once we raise our minimum support to LLVM 10. -extern "C" LLVMValueRef -LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target, - LLVMValueRef Old, LLVMValueRef Source, - LLVMAtomicOrdering Order, - LLVMAtomicOrdering FailureOrder, LLVMBool Weak) { - AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( - unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order), - fromRust(FailureOrder)); - ACXI->setWeak(Weak); - return wrap(ACXI); -} - -enum class LLVMRustSynchronizationScope { - SingleThread, - CrossThread, -}; - -static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) { - switch (Scope) { - case LLVMRustSynchronizationScope::SingleThread: - return SyncScope::SingleThread; - case LLVMRustSynchronizationScope::CrossThread: - return SyncScope::System; - default: - report_fatal_error("bad SynchronizationScope."); - } -} - -extern "C" LLVMValueRef -LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order, - LLVMRustSynchronizationScope Scope) { - return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope))); -} - -enum class LLVMRustAsmDialect { - Att, - Intel, -}; - -static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) { - switch (Dialect) { - case LLVMRustAsmDialect::Att: - return InlineAsm::AD_ATT; - case LLVMRustAsmDialect::Intel: - return InlineAsm::AD_Intel; - default: - report_fatal_error("bad AsmDialect."); - } -} - -extern "C" LLVMValueRef -LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, - char *Constraints, size_t ConstraintsLen, - LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMRustAsmDialect Dialect) { - return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), - StringRef(AsmString, AsmStringLen), - StringRef(Constraints, ConstraintsLen), - HasSideEffects, IsAlignStack, fromRust(Dialect))); -} - -extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, - size_t ConstraintsLen) { - return InlineAsm::Verify(unwrap<FunctionType>(Ty), - StringRef(Constraints, ConstraintsLen)); -} - -extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, - size_t AsmLen) { - unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen)); -} - -typedef DIBuilder *LLVMRustDIBuilderRef; - -template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { - return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr); -} - -#define DIDescriptor DIScope -#define DIArray DINodeArray -#define unwrapDI unwrapDIPtr - -// These values **must** match debuginfo::DIFlags! They also *happen* -// to match LLVM, but that isn't required as we do giant sets of -// matching below. The value shouldn't be directly passed to LLVM. -enum class LLVMRustDIFlags : uint32_t { - FlagZero = 0, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - FlagFwdDecl = (1 << 2), - FlagAppleBlock = (1 << 3), - FlagBlockByrefStruct = (1 << 4), - FlagVirtual = (1 << 5), - FlagArtificial = (1 << 6), - FlagExplicit = (1 << 7), - FlagPrototyped = (1 << 8), - FlagObjcClassComplete = (1 << 9), - FlagObjectPointer = (1 << 10), - FlagVector = (1 << 11), - FlagStaticMember = (1 << 12), - FlagLValueReference = (1 << 13), - FlagRValueReference = (1 << 14), - FlagExternalTypeRef = (1 << 15), - FlagIntroducedVirtual = (1 << 18), - FlagBitField = (1 << 19), - FlagNoReturn = (1 << 20), - // Do not add values that are not supported by the minimum LLVM - // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def -}; - -inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) & - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) | - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) { - return A = A | B; -} - -inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; } - -inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3); -} - -static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { - DINode::DIFlags Result = DINode::DIFlags::FlagZero; - - switch (visibility(Flags)) { - case LLVMRustDIFlags::FlagPrivate: - Result |= DINode::DIFlags::FlagPrivate; - break; - case LLVMRustDIFlags::FlagProtected: - Result |= DINode::DIFlags::FlagProtected; - break; - case LLVMRustDIFlags::FlagPublic: - Result |= DINode::DIFlags::FlagPublic; - break; - default: - // The rest are handled below - break; - } - - if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) { - Result |= DINode::DIFlags::FlagFwdDecl; - } - if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { - Result |= DINode::DIFlags::FlagAppleBlock; - } -#if LLVM_VERSION_LT(10, 0) - if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { - Result |= DINode::DIFlags::FlagBlockByrefStruct; - } -#endif - if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { - Result |= DINode::DIFlags::FlagVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) { - Result |= DINode::DIFlags::FlagArtificial; - } - if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) { - Result |= DINode::DIFlags::FlagExplicit; - } - if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) { - Result |= DINode::DIFlags::FlagPrototyped; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) { - Result |= DINode::DIFlags::FlagObjcClassComplete; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) { - Result |= DINode::DIFlags::FlagObjectPointer; - } - if (isSet(Flags & LLVMRustDIFlags::FlagVector)) { - Result |= DINode::DIFlags::FlagVector; - } - if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) { - Result |= DINode::DIFlags::FlagStaticMember; - } - if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) { - Result |= DINode::DIFlags::FlagLValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { - Result |= DINode::DIFlags::FlagRValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { - Result |= DINode::DIFlags::FlagIntroducedVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) { - Result |= DINode::DIFlags::FlagBitField; - } - if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) { - Result |= DINode::DIFlags::FlagNoReturn; - } - - return Result; -} - -// These values **must** match debuginfo::DISPFlags! They also *happen* -// to match LLVM, but that isn't required as we do giant sets of -// matching below. The value shouldn't be directly passed to LLVM. -enum class LLVMRustDISPFlags : uint32_t { - SPFlagZero = 0, - SPFlagVirtual = 1, - SPFlagPureVirtual = 2, - SPFlagLocalToUnit = (1 << 2), - SPFlagDefinition = (1 << 3), - SPFlagOptimized = (1 << 4), - SPFlagMainSubprogram = (1 << 5), - // Do not add values that are not supported by the minimum LLVM - // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def - // (In LLVM < 8, createFunction supported these as separate bool arguments.) -}; - -inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) { - return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) & - static_cast<uint32_t>(B)); -} - -inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) { - return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) | - static_cast<uint32_t>(B)); -} - -inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) { - return A = A | B; -} - -inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; } - -inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) { - return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3); -} - -static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) { - DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero; - - switch (virtuality(SPFlags)) { - case LLVMRustDISPFlags::SPFlagVirtual: - Result |= DISubprogram::DISPFlags::SPFlagVirtual; - break; - case LLVMRustDISPFlags::SPFlagPureVirtual: - Result |= DISubprogram::DISPFlags::SPFlagPureVirtual; - break; - default: - // The rest are handled below - break; - } - - if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) { - Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit; - } - if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) { - Result |= DISubprogram::DISPFlags::SPFlagDefinition; - } - if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) { - Result |= DISubprogram::DISPFlags::SPFlagOptimized; - } -#if LLVM_VERSION_GE(9, 0) - if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) { - Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram; - } -#endif - - return Result; -} - -enum class LLVMRustDebugEmissionKind { - NoDebug, - FullDebug, - LineTablesOnly, -}; - -static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { - switch (Kind) { - case LLVMRustDebugEmissionKind::NoDebug: - return DICompileUnit::DebugEmissionKind::NoDebug; - case LLVMRustDebugEmissionKind::FullDebug: - return DICompileUnit::DebugEmissionKind::FullDebug; - case LLVMRustDebugEmissionKind::LineTablesOnly: - return DICompileUnit::DebugEmissionKind::LineTablesOnly; - default: - report_fatal_error("bad DebugEmissionKind."); - } -} - -enum class LLVMRustChecksumKind { - None, - MD5, - SHA1, -}; - -static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) { - switch (Kind) { - case LLVMRustChecksumKind::None: - return None; - case LLVMRustChecksumKind::MD5: - return DIFile::ChecksumKind::CSK_MD5; - case LLVMRustChecksumKind::SHA1: - return DIFile::ChecksumKind::CSK_SHA1; - default: - report_fatal_error("bad ChecksumKind."); - } -} - -extern "C" uint32_t LLVMRustDebugMetadataVersion() { - return DEBUG_METADATA_VERSION; -} - -extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } - -extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } - -extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, - uint32_t Value) { - unwrap(M)->addModuleFlag(Module::Warning, Name, Value); -} - -extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) { - return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); -} - -extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { - return new DIBuilder(*unwrap(M)); -} - -extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) { - delete Builder; -} - -extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) { - Builder->finalize(); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( - LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, - const char *Producer, size_t ProducerLen, bool isOptimized, - const char *Flags, unsigned RuntimeVer, - const char *SplitName, size_t SplitNameLen, - LLVMRustDebugEmissionKind Kind) { - auto *File = unwrapDI<DIFile>(FileRef); - - return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen), - isOptimized, Flags, RuntimeVer, - StringRef(SplitName, SplitNameLen), - fromRust(Kind))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( - LLVMRustDIBuilderRef Builder, - const char *Filename, size_t FilenameLen, - const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, - const char *Checksum, size_t ChecksumLen) { - Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind); - Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{}; - if (llvmCSKind) - CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); - return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), - CSInfo)); -} - -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef ParameterTypes) { - return wrap(Builder->createSubroutineType( - DITypeRefArray(unwrap<MDTuple>(ParameterTypes)))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *LinkageName, size_t LinkageNameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags, - LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam, - LLVMMetadataRef Decl) { - DITemplateParameterArray TParams = - DITemplateParameterArray(unwrap<MDTuple>(TParam)); - DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); - DINode::DIFlags llvmFlags = fromRust(Flags); -#if LLVM_VERSION_LT(9, 0) - if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) - llvmFlags |= DINode::DIFlags::FlagMainSubprogram; -#endif - DISubprogram *Sub = Builder->createFunction( - unwrapDI<DIScope>(Scope), - StringRef(Name, NameLen), - StringRef(LinkageName, LinkageNameLen), - unwrapDI<DIFile>(File), LineNo, - unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, - llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl)); - unwrap<Function>(Fn)->setSubprogram(Sub); - return wrap(Sub); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType( - LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, - uint64_t SizeInBits, unsigned Encoding) { - return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) { - return wrap(Builder->createTypedef( - unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File), - LineNo, unwrap<DIScope>(Scope))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy, - uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, - const char *Name, size_t NameLen) { - return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy), - SizeInBits, AlignInBits, - AddressSpace, - StringRef(Name, NameLen))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, - LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, - unsigned RunTimeLang, LLVMMetadataRef VTableHolder, - const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createStructType( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNumber, - SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom), - DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, - unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator, - LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createVariantPart( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNumber, - SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator), - DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags, - LLVMMetadataRef Ty) { - return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), - StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNo, - SizeInBits, AlignInBits, OffsetInBits, - fromRust(Flags), unwrapDI<DIType>(Ty))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, - LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { - llvm::ConstantInt* D = nullptr; - if (Discriminant) { - D = unwrap<llvm::ConstantInt>(Discriminant); - } - return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope), - StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNo, - SizeInBits, AlignInBits, OffsetInBits, D, - fromRust(Flags), unwrapDI<DIType>(Ty))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - LLVMMetadataRef File, unsigned Line, unsigned Col) { - return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope), - unwrapDI<DIFile>(File), Line, Col)); -} - -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, - LLVMMetadataRef File) { - return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope), - unwrapDI<DIFile>(File))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, - const char *Name, size_t NameLen, - const char *LinkageName, size_t LinkageNameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V, - LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) { - llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V)); - - llvm::DIExpression *InitExpr = nullptr; - if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) { - InitExpr = Builder->createConstantValueExpression( - IntVal->getValue().getSExtValue()); - } else if (llvm::ConstantFP *FPVal = - llvm::dyn_cast<llvm::ConstantFP>(InitVal)) { - InitExpr = Builder->createConstantValueExpression( - FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); - } - - llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( - unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen), - StringRef(LinkageName, LinkageNameLen), - unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit, -#if LLVM_VERSION_GE(10, 0) - /* isDefined */ true, -#endif - InitExpr, unwrapDIPtr<MDNode>(Decl), - /* templateParams */ nullptr, - AlignInBits); - - InitVal->setMetadata("dbg", VarExpr); - - return wrap(VarExpr); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( - LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags, - unsigned ArgNo, uint32_t AlignInBits) { - if (Tag == 0x100) { // DW_TAG_auto_variable - return wrap(Builder->createAutoVariable( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNo, - unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits)); - } else { - return wrap(Builder->createParameterVariable( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo, - unwrapDI<DIFile>(File), LineNo, - unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags))); - } -} - -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size, - uint32_t AlignInBits, LLVMMetadataRef Ty, - LLVMMetadataRef Subscripts) { - return wrap( - Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty), - DINodeArray(unwrapDI<MDTuple>(Subscripts)))); -} - -extern "C" LLVMMetadataRef -LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo, - int64_t Count) { - return wrap(Builder->getOrCreateSubrange(Lo, Count)); -} - -extern "C" LLVMMetadataRef -LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef *Ptr, unsigned Count) { - Metadata **DataValue = unwrap(Ptr); - return wrap( - Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get()); -} - -extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( - LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, - int64_t *AddrOps, unsigned AddrOpsCount, LLVMValueRef DL, - LLVMBasicBlockRef InsertAtEnd) { - return wrap(Builder->insertDeclare( - unwrap(V), unwrap<DILocalVariable>(VarInfo), - Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)), - DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())), - unwrap(InsertAtEnd))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( - LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, - int64_t Value, bool IsUnsigned) { - return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned)); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMMetadataRef Elements, - LLVMMetadataRef ClassTy, bool IsScoped) { - return wrap(Builder->createEnumerationType( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNumber, - SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)), - unwrapDI<DIType>(ClassTy), "", IsScoped)); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements, - unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) { - return wrap(Builder->createUnionType( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File), - LineNumber, SizeInBits, AlignInBits, fromRust(Flags), - DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, - StringRef(UniqueId, UniqueIdLen))); -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, LLVMMetadataRef Ty) { -#if LLVM_VERSION_GE(11, 0) - bool IsDefault = false; // FIXME: should we ever set this true? - return wrap(Builder->createTemplateTypeParameter( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault)); -#else - return wrap(Builder->createTemplateTypeParameter( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty))); -#endif -} - -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, bool ExportSymbols) { - return wrap(Builder->createNameSpace( - unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols - )); -} - -extern "C" void -LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef CompositeTy, - LLVMMetadataRef Elements, - LLVMMetadataRef Params) { - DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy); - Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)), - DINodeArray(unwrap<MDTuple>(Params))); -} - -extern "C" LLVMValueRef -LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line, - unsigned Column, LLVMMetadataRef Scope, - LLVMMetadataRef InlinedAt) { - LLVMContext &Context = *unwrap(ContextRef); - - DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope), - unwrapDIPtr<MDNode>(InlinedAt)); - - return wrap(MetadataAsValue::get(Context, debug_loc.getAsMDNode())); -} - -extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { - return dwarf::DW_OP_deref; -} - -extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() { - return dwarf::DW_OP_plus_uconst; -} - -extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { - RawRustStringOstream OS(Str); - unwrap<llvm::Type>(Ty)->print(OS); -} - -extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, - RustStringRef Str) { - RawRustStringOstream OS(Str); - if (!V) { - OS << "(null)"; - } else { - OS << "("; - unwrap<llvm::Value>(V)->getType()->print(OS); - OS << ":"; - unwrap<llvm::Value>(V)->print(OS); - OS << ")"; - } -} - -// 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<section_iterator *>(SI); -} - -extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI, - const char **Ptr) { -#if LLVM_VERSION_GE(10, 0) - auto NameOrErr = (*unwrap(SI))->getName(); - if (!NameOrErr) - report_fatal_error(NameOrErr.takeError()); - *Ptr = NameOrErr->data(); - return NameOrErr->size(); -#else - StringRef Ret; - if (std::error_code EC = (*unwrap(SI))->getName(Ret)) - report_fatal_error(EC.message()); - *Ptr = Ret.data(); - return Ret.size(); -#endif -} - -// LLVMArrayType function does not support 64-bit ElementCount -extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, - uint64_t ElementCount) { - return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); -} - -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) - -extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { - RawRustStringOstream OS(Str); - unwrap(T)->print(OS); -} - -extern "C" void LLVMRustUnpackOptimizationDiagnostic( - LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut, - LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column, - RustStringRef FilenameOut, RustStringRef MessageOut) { - // Undefined to call this not on an optimization diagnostic! - llvm::DiagnosticInfoOptimizationBase *Opt = - static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI)); - - RawRustStringOstream PassNameOS(PassNameOut); - PassNameOS << Opt->getPassName(); - *FunctionOut = wrap(&Opt->getFunction()); - - RawRustStringOstream FilenameOS(FilenameOut); - DiagnosticLocation loc = Opt->getLocation(); - if (loc.isValid()) { - *Line = loc.getLine(); - *Column = loc.getColumn(); - FilenameOS << loc.getAbsolutePath(); - } - - RawRustStringOstream MessageOS(MessageOut); - MessageOS << Opt->getMsg(); -} - -enum class LLVMRustDiagnosticLevel { - Error, - Warning, - Note, - Remark, -}; - -extern "C" void -LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, - LLVMRustDiagnosticLevel *LevelOut, - unsigned *CookieOut, - LLVMTwineRef *MessageOut, - LLVMValueRef *InstructionOut) { - // Undefined to call this not on an inline assembly diagnostic! - llvm::DiagnosticInfoInlineAsm *IA = - static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI)); - - *CookieOut = IA->getLocCookie(); - *MessageOut = wrap(&IA->getMsgStr()); - *InstructionOut = wrap(IA->getInstruction()); - - switch (IA->getSeverity()) { - case DS_Error: - *LevelOut = LLVMRustDiagnosticLevel::Error; - break; - case DS_Warning: - *LevelOut = LLVMRustDiagnosticLevel::Warning; - break; - case DS_Note: - *LevelOut = LLVMRustDiagnosticLevel::Note; - break; - case DS_Remark: - *LevelOut = LLVMRustDiagnosticLevel::Remark; - break; - default: - report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); - } -} - -extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, - RustStringRef Str) { - RawRustStringOstream OS(Str); - DiagnosticPrinterRawOStream DP(OS); - unwrap(DI)->print(DP); -} - -enum class LLVMRustDiagnosticKind { - Other, - InlineAsm, - StackSize, - DebugMetadataVersion, - SampleProfile, - OptimizationRemark, - OptimizationRemarkMissed, - OptimizationRemarkAnalysis, - OptimizationRemarkAnalysisFPCommute, - OptimizationRemarkAnalysisAliasing, - OptimizationRemarkOther, - OptimizationFailure, - PGOProfile, - Linker, -}; - -static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { - switch (Kind) { - case DK_InlineAsm: - return LLVMRustDiagnosticKind::InlineAsm; - case DK_StackSize: - return LLVMRustDiagnosticKind::StackSize; - case DK_DebugMetadataVersion: - return LLVMRustDiagnosticKind::DebugMetadataVersion; - case DK_SampleProfile: - return LLVMRustDiagnosticKind::SampleProfile; - case DK_OptimizationRemark: - return LLVMRustDiagnosticKind::OptimizationRemark; - case DK_OptimizationRemarkMissed: - return LLVMRustDiagnosticKind::OptimizationRemarkMissed; - case DK_OptimizationRemarkAnalysis: - return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis; - case DK_OptimizationRemarkAnalysisFPCommute: - return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute; - case DK_OptimizationRemarkAnalysisAliasing: - return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing; - case DK_PGOProfile: - return LLVMRustDiagnosticKind::PGOProfile; - case DK_Linker: - return LLVMRustDiagnosticKind::Linker; - default: - return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) - ? LLVMRustDiagnosticKind::OptimizationRemarkOther - : LLVMRustDiagnosticKind::Other; - } -} - -extern "C" LLVMRustDiagnosticKind -LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) { - return toRust((DiagnosticKind)unwrap(DI)->getKind()); -} - -// This is kept distinct from LLVMGetTypeKind, because when -// a new type kind is added, the Rust-side enum must be -// updated or UB will result. -extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { - switch (unwrap(Ty)->getTypeID()) { - case Type::VoidTyID: - return LLVMVoidTypeKind; - case Type::HalfTyID: - return LLVMHalfTypeKind; - case Type::FloatTyID: - return LLVMFloatTypeKind; - case Type::DoubleTyID: - return LLVMDoubleTypeKind; - case Type::X86_FP80TyID: - return LLVMX86_FP80TypeKind; - case Type::FP128TyID: - return LLVMFP128TypeKind; - case Type::PPC_FP128TyID: - return LLVMPPC_FP128TypeKind; - case Type::LabelTyID: - return LLVMLabelTypeKind; - case Type::MetadataTyID: - return LLVMMetadataTypeKind; - case Type::IntegerTyID: - return LLVMIntegerTypeKind; - case Type::FunctionTyID: - return LLVMFunctionTypeKind; - case Type::StructTyID: - return LLVMStructTypeKind; - case Type::ArrayTyID: - return LLVMArrayTypeKind; - case Type::PointerTyID: - return LLVMPointerTypeKind; -#if LLVM_VERSION_GE(11, 0) - case Type::FixedVectorTyID: - return LLVMVectorTypeKind; -#else - case Type::VectorTyID: - return LLVMVectorTypeKind; -#endif - case Type::X86_MMXTyID: - return LLVMX86_MMXTypeKind; - case Type::TokenTyID: - return LLVMTokenTypeKind; -#if LLVM_VERSION_GE(11, 0) - case Type::ScalableVectorTyID: - return LLVMScalableVectorTypeKind; - case Type::BFloatTyID: - return LLVMBFloatTypeKind; -#endif - } - report_fatal_error("Unhandled TypeID."); -} - -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) - -extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( - LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { - unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); -} - -extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, - RustStringRef MessageOut, - RustStringRef BufferOut, - LLVMRustDiagnosticLevel* LevelOut, - unsigned* LocOut, - unsigned* RangesOut, - size_t* NumRanges) { - SMDiagnostic& D = *unwrap(DRef); - RawRustStringOstream MessageOS(MessageOut); - MessageOS << D.getMessage(); - - switch (D.getKind()) { - case SourceMgr::DK_Error: - *LevelOut = LLVMRustDiagnosticLevel::Error; - break; - case SourceMgr::DK_Warning: - *LevelOut = LLVMRustDiagnosticLevel::Warning; - break; - case SourceMgr::DK_Note: - *LevelOut = LLVMRustDiagnosticLevel::Note; - break; - case SourceMgr::DK_Remark: - *LevelOut = LLVMRustDiagnosticLevel::Remark; - break; - default: - report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); - } - - if (D.getLoc() == SMLoc()) - return false; - - const SourceMgr &LSM = *D.getSourceMgr(); - const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize()); - - *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart(); - - *NumRanges = std::min(*NumRanges, D.getRanges().size()); - size_t LineStart = *LocOut - (size_t)D.getColumnNo(); - for (size_t i = 0; i < *NumRanges; i++) { - RangesOut[i * 2] = LineStart + D.getRanges()[i].first; - RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second; - } - - return true; -} - -extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, - LLVMValueRef ParentPad, - unsigned ArgCount, - LLVMValueRef *LLArgs, - const char *Name) { - Value **Args = unwrap(LLArgs); - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCleanupPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B, - LLVMValueRef CleanupPad, - LLVMBasicBlockRef UnwindBB) { - CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad)); - return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB))); -} - -extern "C" LLVMValueRef -LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, - unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) { - Value **Args = unwrap(LLArgs); - return wrap(unwrap(B)->CreateCatchPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B, - LLVMValueRef Pad, - LLVMBasicBlockRef BB) { - return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)), - unwrap(BB))); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B, - LLVMValueRef ParentPad, - LLVMBasicBlockRef BB, - unsigned NumHandlers, - const char *Name) { - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB), - NumHandlers, Name)); -} - -extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, - LLVMBasicBlockRef Handler) { - Value *CatchSwitch = unwrap(CatchSwitchRef); - cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler)); -} - -extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, - LLVMValueRef *Inputs, - unsigned NumInputs) { - return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs)); -} - -extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { - delete Bundle; -} - -extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, - LLVMValueRef *Args, unsigned NumArgs, - OperandBundleDef *Bundle) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType()); - unsigned Len = Bundle ? 1 : 0; - ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); - return wrap(unwrap(B)->CreateCall( - FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles)); -} - -extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { - return wrap(llvm::Intrinsic::getDeclaration(unwrap(M), - (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment)); -} - -extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Src, unsigned SrcAlign, - LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), MaybeAlign(DstAlign), - unwrap(Src), MaybeAlign(SrcAlign), - unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif -} - -extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Src, unsigned SrcAlign, - LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), MaybeAlign(DstAlign), - unwrap(Src), MaybeAlign(SrcAlign), - unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif -} - -extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Val, - LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); -#endif -} - -extern "C" LLVMValueRef -LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, LLVMBasicBlockRef Then, - LLVMBasicBlockRef Catch, OperandBundleDef *Bundle, - const char *Name) { - Value *Callee = unwrap(Fn); - FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType()); - unsigned Len = Bundle ? 1 : 0; - ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len); - return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), - makeArrayRef(unwrap(Args), NumArgs), - Bundles, Name)); -} - -extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, - LLVMBasicBlockRef BB) { - auto Point = unwrap(BB)->getFirstInsertionPt(); - unwrap(B)->SetInsertPoint(unwrap(BB), Point); -} - -extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, - const char *Name, size_t NameLen) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - GlobalObject *GV = unwrap<GlobalObject>(V); - if (!TargetTriple.isOSBinFormatMachO()) { - StringRef NameRef(Name, NameLen); - GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef)); - } -} - -extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) { - GlobalObject *GV = unwrap<GlobalObject>(V); - GV->setComdat(nullptr); -} - -enum class LLVMRustLinkage { - ExternalLinkage = 0, - AvailableExternallyLinkage = 1, - LinkOnceAnyLinkage = 2, - LinkOnceODRLinkage = 3, - WeakAnyLinkage = 4, - WeakODRLinkage = 5, - AppendingLinkage = 6, - InternalLinkage = 7, - PrivateLinkage = 8, - ExternalWeakLinkage = 9, - CommonLinkage = 10, -}; - -static LLVMRustLinkage toRust(LLVMLinkage Linkage) { - switch (Linkage) { - case LLVMExternalLinkage: - return LLVMRustLinkage::ExternalLinkage; - case LLVMAvailableExternallyLinkage: - return LLVMRustLinkage::AvailableExternallyLinkage; - case LLVMLinkOnceAnyLinkage: - return LLVMRustLinkage::LinkOnceAnyLinkage; - case LLVMLinkOnceODRLinkage: - return LLVMRustLinkage::LinkOnceODRLinkage; - case LLVMWeakAnyLinkage: - return LLVMRustLinkage::WeakAnyLinkage; - case LLVMWeakODRLinkage: - return LLVMRustLinkage::WeakODRLinkage; - case LLVMAppendingLinkage: - return LLVMRustLinkage::AppendingLinkage; - case LLVMInternalLinkage: - return LLVMRustLinkage::InternalLinkage; - case LLVMPrivateLinkage: - return LLVMRustLinkage::PrivateLinkage; - case LLVMExternalWeakLinkage: - return LLVMRustLinkage::ExternalWeakLinkage; - case LLVMCommonLinkage: - return LLVMRustLinkage::CommonLinkage; - default: - report_fatal_error("Invalid LLVMRustLinkage value!"); - } -} - -static LLVMLinkage fromRust(LLVMRustLinkage Linkage) { - switch (Linkage) { - case LLVMRustLinkage::ExternalLinkage: - return LLVMExternalLinkage; - case LLVMRustLinkage::AvailableExternallyLinkage: - return LLVMAvailableExternallyLinkage; - case LLVMRustLinkage::LinkOnceAnyLinkage: - return LLVMLinkOnceAnyLinkage; - case LLVMRustLinkage::LinkOnceODRLinkage: - return LLVMLinkOnceODRLinkage; - case LLVMRustLinkage::WeakAnyLinkage: - return LLVMWeakAnyLinkage; - case LLVMRustLinkage::WeakODRLinkage: - return LLVMWeakODRLinkage; - case LLVMRustLinkage::AppendingLinkage: - return LLVMAppendingLinkage; - case LLVMRustLinkage::InternalLinkage: - return LLVMInternalLinkage; - case LLVMRustLinkage::PrivateLinkage: - return LLVMPrivateLinkage; - case LLVMRustLinkage::ExternalWeakLinkage: - return LLVMExternalWeakLinkage; - case LLVMRustLinkage::CommonLinkage: - return LLVMCommonLinkage; - } - report_fatal_error("Invalid LLVMRustLinkage value!"); -} - -extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) { - return toRust(LLVMGetLinkage(V)); -} - -extern "C" void LLVMRustSetLinkage(LLVMValueRef V, - LLVMRustLinkage RustLinkage) { - LLVMSetLinkage(V, fromRust(RustLinkage)); -} - -// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of -// the common sizes (1, 8, 16, 32, 64, 128 bits) -extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low) -{ - auto C = unwrap<llvm::ConstantInt>(CV); - if (C->getBitWidth() > 128) { return false; } - APInt AP; - if (sext) { - AP = C->getValue().sextOrSelf(128); - } else { - AP = C->getValue().zextOrSelf(128); - } - *low = AP.getLoBits(64).getZExtValue(); - *high = AP.getHiBits(64).getZExtValue(); - return true; -} - -enum class LLVMRustVisibility { - Default = 0, - Hidden = 1, - Protected = 2, -}; - -static LLVMRustVisibility toRust(LLVMVisibility Vis) { - switch (Vis) { - case LLVMDefaultVisibility: - return LLVMRustVisibility::Default; - case LLVMHiddenVisibility: - return LLVMRustVisibility::Hidden; - case LLVMProtectedVisibility: - return LLVMRustVisibility::Protected; - } - report_fatal_error("Invalid LLVMRustVisibility value!"); -} - -static LLVMVisibility fromRust(LLVMRustVisibility Vis) { - switch (Vis) { - case LLVMRustVisibility::Default: - return LLVMDefaultVisibility; - case LLVMRustVisibility::Hidden: - return LLVMHiddenVisibility; - case LLVMRustVisibility::Protected: - return LLVMProtectedVisibility; - } - report_fatal_error("Invalid LLVMRustVisibility value!"); -} - -extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { - return toRust(LLVMGetVisibility(V)); -} - -// Oh hey, a binding that makes sense for once? (because LLVM’s own do not) -extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val, - LLVMTypeRef DestTy, bool isSigned) { - return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, "")); -} - -extern "C" void LLVMRustSetVisibility(LLVMValueRef V, - LLVMRustVisibility RustVisibility) { - LLVMSetVisibility(V, fromRust(RustVisibility)); -} - -struct LLVMRustModuleBuffer { - std::string data; -}; - -extern "C" LLVMRustModuleBuffer* -LLVMRustModuleBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) - auto Ret = std::make_unique<LLVMRustModuleBuffer>(); -#else - auto Ret = llvm::make_unique<LLVMRustModuleBuffer>(); -#endif - { - raw_string_ostream OS(Ret->data); - { - legacy::PassManager PM; - PM.add(createBitcodeWriterPass(OS)); - PM.run(*unwrap(M)); - } - } - return Ret.release(); -} - -extern "C" void -LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) { - delete Buffer; -} - -extern "C" const void* -LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) { - return Buffer->data.data(); -} - -extern "C" size_t -LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) { - return Buffer->data.length(); -} - -extern "C" uint64_t -LLVMRustModuleCost(LLVMModuleRef M) { - auto f = unwrap(M)->functions(); - return std::distance(std::begin(f), std::end(f)); -} - -// Vector reductions: -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { - return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { - return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { - return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); -} -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { - return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); -} - -extern "C" LLVMValueRef -LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { - return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS))); -} -extern "C" LLVMValueRef -LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { - return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); -} diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h deleted file mode 100644 index 57b8664d3b6..00000000000 --- a/src/rustllvm/rustllvm.h +++ /dev/null @@ -1,115 +0,0 @@ -#include "llvm-c/BitReader.h" -#include "llvm-c/Core.h" -#include "llvm-c/Object.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Analysis/Lint.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Memory.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Vectorize.h" - -#define LLVM_VERSION_GE(major, minor) \ - (LLVM_VERSION_MAJOR > (major) || \ - LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor)) - -#define LLVM_VERSION_EQ(major, minor) \ - (LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor)) - -#define LLVM_VERSION_LE(major, minor) \ - (LLVM_VERSION_MAJOR < (major) || \ - LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor)) - -#define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor))) - -#include "llvm/IR/LegacyPassManager.h" - -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/Bitcode/BitcodeWriter.h" - -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/Linker/Linker.h" - -extern "C" void LLVMRustSetLastError(const char *); - -enum class LLVMRustResult { Success, Failure }; - -enum LLVMRustAttribute { - AlwaysInline = 0, - ByVal = 1, - Cold = 2, - InlineHint = 3, - MinSize = 4, - Naked = 5, - NoAlias = 6, - NoCapture = 7, - NoInline = 8, - NonNull = 9, - NoRedZone = 10, - NoReturn = 11, - NoUnwind = 12, - OptimizeForSize = 13, - ReadOnly = 14, - SExt = 15, - StructRet = 16, - UWTable = 17, - ZExt = 18, - InReg = 19, - SanitizeThread = 20, - SanitizeAddress = 21, - SanitizeMemory = 22, - NonLazyBind = 23, - OptimizeNone = 24, - ReturnsTwice = 25, - ReadNone = 26, - InaccessibleMemOnly = 27, -}; - -typedef struct OpaqueRustString *RustStringRef; -typedef struct LLVMOpaqueTwine *LLVMTwineRef; -typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; - -extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr, - size_t Size); - -class RawRustStringOstream : public llvm::raw_ostream { - RustStringRef Str; - uint64_t Pos; - - void write_impl(const char *Ptr, size_t Size) override { - LLVMRustStringWriteImpl(Str, Ptr, Size); - Pos += Size; - } - - uint64_t current_pos() const override { return Pos; } - -public: - explicit RawRustStringOstream(RustStringRef Str) : Str(Str), Pos(0) {} - - ~RawRustStringOstream() { - // LLVM requires this. - flush(); - } -}; |
