Source.cpp revision b316f58fd790ad302b72f569af3e89734ae09db7
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/Analysis/Verifier.h> 22#include <llvm/Bitcode/ReaderWriter.h> 23#include <llvm/IR/LLVMContext.h> 24#include <llvm/Linker.h> 25#include <llvm/IR/Module.h> 26#include <llvm/Support/MemoryBuffer.h> 27#include <llvm/Support/system_error.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 NULL and will NOT take the ownership of pInput. 40static inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext, 41 llvm::MemoryBuffer *pInput) { 42 std::string error; 43 llvm::Module *module = llvm::getLazyBitcodeModule(pInput, pContext, &error); 44 45 if (module == NULL) { 46 ALOGE("Unable to parse the given bitcode file `%s'! (%s)", 47 pInput->getBufferIdentifier(), error.c_str()); 48 } 49 50 return module; 51} 52 53} // end anonymous namespace 54 55namespace bcc { 56 57void Source::setModule(llvm::Module *pModule) { 58 if (!mNoDelete && (mModule != pModule)) delete mModule; 59 mModule = pModule; 60} 61 62Source *Source::CreateFromBuffer(BCCContext &pContext, 63 const char *pName, 64 const char *pBitcode, 65 size_t pBitcodeSize) { 66 llvm::StringRef input_data(pBitcode, pBitcodeSize); 67 llvm::MemoryBuffer *input_memory = 68 llvm::MemoryBuffer::getMemBuffer(input_data, "", false); 69 70 if (input_memory == NULL) { 71 ALOGE("Unable to load bitcode `%s' from buffer!", pName); 72 return NULL; 73 } 74 75 llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 76 input_memory); 77 if (module == NULL) { 78 delete input_memory; 79 return NULL; 80 } 81 82 Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 83 if (result == NULL) { 84 delete module; 85 } 86 87 return result; 88} 89 90Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) { 91 llvm::OwningPtr<llvm::MemoryBuffer> input_data; 92 93 llvm::error_code ec = llvm::MemoryBuffer::getFile(pPath, input_data); 94 if (ec != llvm::error_code::success()) { 95 ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(), 96 ec.message().c_str()); 97 return NULL; 98 } 99 100 llvm::MemoryBuffer *input_memory = input_data.take(); 101 llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 102 input_memory); 103 if (module == NULL) { 104 delete input_memory; 105 return NULL; 106 } 107 108 Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 109 if (result == NULL) { 110 delete module; 111 } 112 113 return result; 114} 115 116Source *Source::CreateFromModule(BCCContext &pContext, llvm::Module &pModule, 117 bool pNoDelete) { 118 std::string ErrorInfo; 119 120 if (llvm::verifyModule(pModule, llvm::ReturnStatusAction, &ErrorInfo)) { 121 ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!", 122 ErrorInfo.c_str()); 123 return NULL; 124 } 125 126 Source *result = new (std::nothrow) Source(pContext, pModule, pNoDelete); 127 if (result == NULL) { 128 ALOGE("Out of memory during Source object allocation for `%s'!", 129 pModule.getModuleIdentifier().c_str()); 130 } 131 return result; 132} 133 134Source::Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete) 135 : mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) { 136 pContext.addSource(*this); 137} 138 139Source::~Source() { 140 mContext.removeSource(*this); 141 if (!mNoDelete) 142 delete mModule; 143} 144 145bool Source::merge(Source &pSource, bool pPreserveSource) { 146 std::string error; 147 llvm::Linker::LinkerMode mode = 148 ((pPreserveSource) ? llvm::Linker::PreserveSource : 149 llvm::Linker::DestroySource); 150 151 if (llvm::Linker::LinkModules(mModule, &pSource.getModule(), 152 mode, &error) != 0) { 153 ALOGE("Failed to link source `%s' with `%s' (%s)!", 154 getIdentifier().c_str(), 155 pSource.getIdentifier().c_str(), 156 error.c_str()); 157 return false; 158 } 159 160 if (!pPreserveSource) { 161 pSource.mNoDelete = true; 162 delete &pSource; 163 } 164 165 return true; 166} 167 168Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) { 169 // Create an empty module 170 llvm::Module *module = 171 new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext); 172 173 if (module == NULL) { 174 ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str()); 175 return NULL; 176 } 177 178 Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 179 if (result == NULL) { 180 delete module; 181 } 182 183 return result; 184} 185 186const std::string &Source::getIdentifier() const { 187 return mModule->getModuleIdentifier(); 188} 189 190} // namespace bcc 191