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