Source.cpp revision a4ded1373d7ad3e503f186e65bccf94126a0f020
1/* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "bcc/Source.h" 18 19#include <new> 20 21#include <llvm/Bitcode/ReaderWriter.h> 22#include <llvm/IR/LLVMContext.h> 23#include <llvm/IR/Module.h> 24#include <llvm/IR/Verifier.h> 25#include <llvm/Linker/Linker.h> 26#include <llvm/Support/MemoryBuffer.h> 27#include "llvm/Support/raw_ostream.h" 28 29#include "bcc/BCCContext.h" 30#include "bcc/Support/Log.h" 31 32#include "BCCContextImpl.h" 33 34namespace { 35 36// Helper function to load the bitcode. This uses "bitcode lazy load" feature to 37// reduce the startup time. On success, return the LLVM module object created 38// and take the ownership of input memory buffer (i.e., pInput). On error, 39// return nullptr and will NOT take the ownership of pInput. 40static inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext, 41 std::unique_ptr<llvm::MemoryBuffer> &&pInput) { 42 llvm::ErrorOr<llvm::Module *> moduleOrError = llvm::getLazyBitcodeModule(std::move(pInput), pContext); 43 if (std::error_code ec = moduleOrError.getError()) { 44 ALOGE("Unable to parse the given bitcode file `%s'! (%s)", 45 pInput->getBufferIdentifier(), ec.message().c_str()); 46 } 47 48 return moduleOrError.get(); 49} 50 51} // end anonymous namespace 52 53namespace bcc { 54 55void Source::setModule(llvm::Module *pModule) { 56 if (!mNoDelete && (mModule != pModule)) delete mModule; 57 mModule = pModule; 58} 59 60Source *Source::CreateFromBuffer(BCCContext &pContext, 61 const char *pName, 62 const char *pBitcode, 63 size_t pBitcodeSize) { 64 llvm::StringRef input_data(pBitcode, pBitcodeSize); 65 std::unique_ptr<llvm::MemoryBuffer> input_memory = 66 llvm::MemoryBuffer::getMemBuffer(input_data, "", false); 67 68 if (input_memory == nullptr) { 69 ALOGE("Unable to load bitcode `%s' from buffer!", pName); 70 return nullptr; 71 } 72 73 llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 74 std::move(input_memory)); 75 if (module == nullptr) { 76 return nullptr; 77 } 78 79 Source *result = CreateFromModule(pContext, pName, *module, /* pNoDelete */false); 80 if (result == nullptr) { 81 delete module; 82 } 83 84 return result; 85} 86 87Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) { 88 89 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error = 90 llvm::MemoryBuffer::getFile(pPath); 91 if (mb_or_error.getError()) { 92 ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(), 93 mb_or_error.getError().message().c_str()); 94 return nullptr; 95 } 96 std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get()); 97 98 std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release()); 99 llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 100 std::move(input_memory)); 101 if (module == nullptr) { 102 return nullptr; 103 } 104 105 Source *result = CreateFromModule(pContext, pPath.c_str(), *module, /* pNoDelete */false); 106 if (result == nullptr) { 107 delete module; 108 } 109 110 return result; 111} 112 113Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule, 114 bool pNoDelete) { 115 std::string ErrorInfo; 116 llvm::raw_string_ostream ErrorStream(ErrorInfo); 117 if (llvm::verifyModule(pModule, &ErrorStream)) { 118 ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!", 119 ErrorStream.str().c_str()); 120 return nullptr; 121 } 122 123 Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete); 124 if (result == nullptr) { 125 ALOGE("Out of memory during Source object allocation for `%s'!", 126 pModule.getModuleIdentifier().c_str()); 127 } 128 return result; 129} 130 131Source::Source(const char* name, BCCContext &pContext, llvm::Module &pModule, 132 bool pNoDelete) 133 : mName(name), mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) { 134 pContext.addSource(*this); 135} 136 137Source::~Source() { 138 mContext.removeSource(*this); 139 if (!mNoDelete) 140 delete mModule; 141} 142 143bool Source::merge(Source &pSource) { 144 // TODO(srhines): Add back logging of actual diagnostics from linking. 145 if (llvm::Linker::LinkModules(mModule, &pSource.getModule()) != 0) { 146 ALOGE("Failed to link source `%s' with `%s'!", 147 getIdentifier().c_str(), pSource.getIdentifier().c_str()); 148 return false; 149 } 150 151 return true; 152} 153 154Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) { 155 // Create an empty module 156 llvm::Module *module = 157 new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext); 158 159 if (module == nullptr) { 160 ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str()); 161 return nullptr; 162 } 163 164 Source *result = CreateFromModule(pContext, pName.c_str(), *module, /* pNoDelete */false); 165 if (result == nullptr) { 166 delete module; 167 } 168 169 return result; 170} 171 172const std::string &Source::getIdentifier() const { 173 return mModule->getModuleIdentifier(); 174} 175 176} // namespace bcc 177