//===- RustWrapper.cpp - Rust wrapper for core functions --------*- C++ -*-=== // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------=== // // This file defines alternate interfaces to core functions that are more // readily callable by Rust's FFI. // //===----------------------------------------------------------------------=== #include "llvm/LLVMContext.h" #include "llvm/Linker.h" #include "llvm/PassManager.h" #include "llvm/ADT/Triple.h" #include "llvm/Assembly/Parser.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Host.h" #include "llvm-c/Core.h" #include "llvm-c/BitReader.h" #include "llvm-c/Object.h" #include using namespace llvm; static const char *LLVMRustError; extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { LLVMMemoryBufferRef MemBuf = NULL; LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, const_cast(&LLVMRustError)); return MemBuf; } extern "C" const char *LLVMRustGetLastError(void) { return LLVMRustError; } extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); extern "C" void LLVMRustAddPrintModulePass(LLVMPassManagerRef PMR, LLVMModuleRef M, const char* path) { PassManager *PM = unwrap(PMR); std::string ErrorInfo; raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); formatted_raw_ostream FOS(OS); PM->add(createPrintModulePass(&FOS)); PM->run(*unwrap(M)); } extern "C" bool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src) { static std::string err; // For some strange reason, unwrap() doesn't work here. "No matching // function" error. Module *DM = reinterpret_cast(Dest); Module *SM = reinterpret_cast(Src); if (Linker::LinkModules(DM, SM, Linker::DestroySource, &err)) { LLVMRustError = err.c_str(); return false; } return true; } extern "C" void LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, LLVMModuleRef M, const char *triple, const char *path, TargetMachine::CodeGenFileType FileType, CodeGenOpt::Level OptLevel, bool EnableSegmentedStacks) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); TargetOptions Options; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; std::string Err; const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err); std::string FeaturesStr; std::string Trip(triple); std::string CPUStr = llvm::sys::getHostCPUName(); TargetMachine *Target = TheTarget->createTargetMachine(Trip, CPUStr, FeaturesStr, Options, Reloc::PIC_, CodeModel::Default, OptLevel); bool NoVerify = false; PassManager *PM = unwrap(PMR); std::string ErrorInfo; raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); formatted_raw_ostream FOS(OS); bool foo = Target->addPassesToEmitFile(*PM, FOS, FileType, NoVerify); assert(!foo); (void)foo; PM->run(*unwrap(M)); delete Target; } extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { SMDiagnostic d; Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); if (m) { return wrap(m); } else { LLVMRustError = d.getMessage().c_str(); return NULL; } } extern "C" LLVMModuleRef LLVMRustParseBitcode(LLVMMemoryBufferRef MemBuf) { LLVMModuleRef M; return LLVMParseBitcode(MemBuf, &M, const_cast(&LLVMRustError)) ? NULL : M; } extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N, LLVMBool SignExtend) { return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend); } extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy, unsigned N_hi, unsigned N_lo, LLVMBool SignExtend) { unsigned long long N = N_hi; N <<= 32; N |= N_lo; return LLVMConstInt(IntTy, N, SignExtend); } extern bool llvm::TimePassesIsEnabled; extern "C" void LLVMRustEnableTimePasses() { TimePassesIsEnabled = true; } extern "C" void LLVMRustPrintPassTimings() { raw_fd_ostream OS (2, false); // stderr. TimerGroup::printAll(OS); } extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, const char* Name, LLVMTypeRef FunctionTy) { return wrap(unwrap(M)->getOrInsertFunction(Name, unwrap(FunctionTy))); }