/src/rustllvm/RustWrapper.cpp
C++ | 192 lines | 150 code | 25 blank | 17 comment | 4 complexity | d7d2ca0f053d50105a03adf33c2ba2d6 MD5 | raw file
1//===- RustWrapper.cpp - Rust wrapper for core functions --------*- C++ -*-=== 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------=== 9// 10// This file defines alternate interfaces to core functions that are more 11// readily callable by Rust's FFI. 12// 13//===----------------------------------------------------------------------=== 14 15#include "llvm/LLVMContext.h" 16#include "llvm/Linker.h" 17#include "llvm/PassManager.h" 18#include "llvm/ADT/Triple.h" 19#include "llvm/Assembly/Parser.h" 20#include "llvm/Assembly/PrintModulePass.h" 21#include "llvm/Support/FormattedStream.h" 22#include "llvm/Support/Timer.h" 23#include "llvm/Support/raw_ostream.h" 24#include "llvm/Target/TargetMachine.h" 25#include "llvm/Support/TargetSelect.h" 26#include "llvm/Support/TargetRegistry.h" 27#include "llvm/Support/SourceMgr.h" 28#include "llvm/Target/TargetOptions.h" 29#include "llvm/Support/Host.h" 30#include "llvm/Support/Debug.h" 31#include "llvm-c/Core.h" 32#include "llvm-c/BitReader.h" 33#include "llvm-c/Object.h" 34#include <cstdlib> 35 36using namespace llvm; 37 38static const char *LLVMRustError; 39 40extern "C" LLVMMemoryBufferRef 41LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { 42 LLVMMemoryBufferRef MemBuf = NULL; 43 LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, 44 const_cast<char **>(&LLVMRustError)); 45 return MemBuf; 46} 47 48extern "C" const char *LLVMRustGetLastError(void) { 49 return LLVMRustError; 50} 51 52extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); 53 54extern "C" void LLVMRustAddPrintModulePass(LLVMPassManagerRef PMR, 55 LLVMModuleRef M, 56 const char* path) { 57 PassManager *PM = unwrap<PassManager>(PMR); 58 std::string ErrorInfo; 59 raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); 60 formatted_raw_ostream FOS(OS); 61 PM->add(createPrintModulePass(&FOS)); 62 PM->run(*unwrap(M)); 63} 64 65void LLVMInitializeX86TargetInfo(); 66void LLVMInitializeX86Target(); 67void LLVMInitializeX86TargetMC(); 68void LLVMInitializeX86AsmPrinter(); 69void LLVMInitializeX86AsmParser(); 70 71extern "C" bool 72LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, 73 LLVMModuleRef M, 74 const char *triple, 75 const char *path, 76 TargetMachine::CodeGenFileType FileType, 77 CodeGenOpt::Level OptLevel, 78 bool EnableSegmentedStacks) { 79 80 // Only initialize the platforms supported by Rust here, 81 // because using --llvm-root will have multiple platforms 82 // that rustllvm doesn't actually link to and it's pointless to put target info 83 // into the registry that Rust can not generate machine code for. 84 85 LLVMInitializeX86TargetInfo(); 86 LLVMInitializeX86Target(); 87 LLVMInitializeX86TargetMC(); 88 LLVMInitializeX86AsmPrinter(); 89 LLVMInitializeX86AsmParser(); 90 91 TargetOptions Options; 92 Options.NoFramePointerElim = true; 93 Options.EnableSegmentedStacks = EnableSegmentedStacks; 94 95 std::string Err; 96 const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err); 97 std::string FeaturesStr; 98 std::string Trip(triple); 99 std::string CPUStr("generic"); 100 TargetMachine *Target = 101 TheTarget->createTargetMachine(Trip, CPUStr, FeaturesStr, 102 Options, Reloc::PIC_, 103 CodeModel::Default, OptLevel); 104 bool NoVerify = false; 105 PassManager *PM = unwrap<PassManager>(PMR); 106 std::string ErrorInfo; 107 raw_fd_ostream OS(path, ErrorInfo, 108 raw_fd_ostream::F_Binary); 109 if (ErrorInfo != "") { 110 LLVMRustError = ErrorInfo.c_str(); 111 return false; 112 } 113 formatted_raw_ostream FOS(OS); 114 115 bool foo = Target->addPassesToEmitFile(*PM, FOS, FileType, NoVerify); 116 assert(!foo); 117 (void)foo; 118 PM->run(*unwrap(M)); 119 delete Target; 120 return true; 121} 122 123extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { 124 125 SMDiagnostic d; 126 Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); 127 if (m) { 128 return wrap(m); 129 } else { 130 LLVMRustError = d.getMessage().c_str(); 131 return NULL; 132 } 133} 134 135extern "C" LLVMModuleRef LLVMRustParseBitcode(LLVMMemoryBufferRef MemBuf) { 136 LLVMModuleRef M; 137 return LLVMParseBitcode(MemBuf, &M, const_cast<char **>(&LLVMRustError)) 138 ? NULL : M; 139} 140 141extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N, 142 LLVMBool SignExtend) { 143 return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend); 144} 145 146extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy, 147 unsigned N_hi, 148 unsigned N_lo, 149 LLVMBool SignExtend) { 150 unsigned long long N = N_hi; 151 N <<= 32; 152 N |= N_lo; 153 return LLVMConstInt(IntTy, N, SignExtend); 154} 155 156extern bool llvm::TimePassesIsEnabled; 157extern "C" void LLVMRustEnableTimePasses() { 158 TimePassesIsEnabled = true; 159} 160 161extern "C" void LLVMRustPrintPassTimings() { 162 raw_fd_ostream OS (2, false); // stderr. 163 TimerGroup::printAll(OS); 164} 165 166extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, 167 const char* Name, 168 LLVMTypeRef FunctionTy) { 169 return wrap(unwrap(M)->getOrInsertFunction(Name, 170 unwrap<FunctionType>(FunctionTy))); 171} 172 173extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { 174 return wrap(Type::getMetadataTy(*unwrap(C))); 175} 176extern "C" LLVMTypeRef LLVMMetadataType(void) { 177 return LLVMMetadataTypeInContext(LLVMGetGlobalContext()); 178} 179 180extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, 181 AtomicRMWInst::BinOp op, 182 LLVMValueRef target, 183 LLVMValueRef source, 184 AtomicOrdering order) { 185 return wrap(unwrap(B)->CreateAtomicRMW(op, 186 unwrap(target), unwrap(source), 187 order)); 188} 189 190extern "C" void LLVMSetDebug(int Enabled) { 191 DebugFlag = Enabled; 192}