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 "Log.h" 20#include "bcc/BCCContext.h" 21 22#include <new> 23 24#include <llvm/ADT/STLExtras.h> 25#include <llvm/ADT/StringExtras.h> 26#include <llvm/Bitcode/ReaderWriter.h> 27#include <llvm/IR/LLVMContext.h> 28#include <llvm/IR/Module.h> 29#include <llvm/IR/Verifier.h> 30#include <llvm/Linker/Linker.h> 31#include <llvm/Support/MemoryBuffer.h> 32#include "llvm/Support/raw_ostream.h" 33 34#include "Assert.h" 35#include "bcinfo/BitcodeWrapper.h" 36#include "bcinfo/MetadataExtractor.h" 37 38#include "BCCContextImpl.h" 39 40namespace { 41 42// Helper function to load the bitcode. This uses "bitcode lazy load" feature to 43// reduce the startup time. On success, return the LLVM module object created 44// and take the ownership of input memory buffer (i.e., pInput). On error, 45// return nullptr and will NOT take the ownership of pInput. 46static inline std::unique_ptr<llvm::Module> helper_load_bitcode(llvm::LLVMContext &pContext, 47 std::unique_ptr<llvm::MemoryBuffer> &&pInput) { 48 llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError 49 = llvm::getLazyBitcodeModule(std::move(pInput), pContext); 50 if (std::error_code ec = moduleOrError.getError()) { 51 ALOGE("Unable to parse the given bitcode file `%s'! (%s)", 52 pInput->getBufferIdentifier(), ec.message().c_str()); 53 } 54 55 return std::move(moduleOrError.get()); 56} 57 58static void helper_get_module_metadata_from_bitcode_wrapper( 59 uint32_t *compilerVersion, uint32_t *optimizationLevel, 60 const bcinfo::BitcodeWrapper &wrapper) { 61 *compilerVersion = wrapper.getCompilerVersion(); 62 *optimizationLevel = wrapper.getOptimizationLevel(); 63} 64 65static void helper_set_module_metadata_from_bitcode_wrapper(llvm::Module &module, 66 const uint32_t compilerVersion, 67 const uint32_t optimizationLevel) { 68 llvm::LLVMContext &llvmContext = module.getContext(); 69 70 llvm::NamedMDNode *const wrapperMDNode = 71 module.getOrInsertNamedMetadata(bcinfo::MetadataExtractor::kWrapperMetadataName); 72 bccAssert(wrapperMDNode->getNumOperands() == 0); // expect to have just now created this node 73 74 llvm::SmallVector<llvm::Metadata *, 2> wrapperInfo = { 75 llvm::MDString::get(llvmContext, llvm::utostr(compilerVersion)), 76 llvm::MDString::get(llvmContext, llvm::utostr(optimizationLevel)) 77 }; 78 79 wrapperMDNode->addOperand(llvm::MDTuple::get(llvmContext, wrapperInfo)); 80} 81 82} // end anonymous namespace 83 84namespace bcc { 85 86unsigned Source::getCompilerVersion() const { 87 return bcinfo::MetadataExtractor(&getModule()).getCompilerVersion(); 88} 89 90void Source::getWrapperInformation(unsigned *compilerVersion, 91 unsigned *optimizationLevel) const { 92 const bcinfo::MetadataExtractor &me = bcinfo::MetadataExtractor(&getModule()); 93 *compilerVersion = me.getCompilerVersion(); 94 *optimizationLevel = me.getOptimizationLevel(); 95} 96 97void Source::setModule(llvm::Module *pModule) { 98 if (!mNoDelete && (mModule != pModule)) delete mModule; 99 mModule = pModule; 100} 101 102Source *Source::CreateFromBuffer(BCCContext &pContext, 103 const char *pName, 104 const char *pBitcode, 105 size_t pBitcodeSize) { 106 llvm::StringRef input_data(pBitcode, pBitcodeSize); 107 std::unique_ptr<llvm::MemoryBuffer> input_memory = 108 llvm::MemoryBuffer::getMemBuffer(input_data, "", false); 109 110 if (input_memory == nullptr) { 111 ALOGE("Unable to load bitcode `%s' from buffer!", pName); 112 return nullptr; 113 } 114 115 auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext, 116 std::move(input_memory)); 117 118 // Release the managed llvm::Module* since this object gets deleted either in 119 // the error check below or in ~Source() (since pNoDelete is false). 120 llvm::Module *module = managedModule.release(); 121 if (module == nullptr) { 122 return nullptr; 123 } 124 125 uint32_t compilerVersion, optimizationLevel; 126 helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel, 127 bcinfo::BitcodeWrapper(pBitcode, pBitcodeSize)); 128 Source *result = CreateFromModule(pContext, pName, *module, 129 compilerVersion, optimizationLevel, 130 /* pNoDelete */false); 131 if (result == nullptr) { 132 delete module; 133 } 134 135 return result; 136} 137 138Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) { 139 140 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error = 141 llvm::MemoryBuffer::getFile(pPath); 142 if (mb_or_error.getError()) { 143 ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(), 144 mb_or_error.getError().message().c_str()); 145 return nullptr; 146 } 147 std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get()); 148 149 uint32_t compilerVersion, optimizationLevel; 150 helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel, 151 bcinfo::BitcodeWrapper(input_data->getBufferStart(), 152 input_data->getBufferSize())); 153 154 std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release()); 155 auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext, 156 std::move(input_memory)); 157 158 // Release the managed llvm::Module* since this object gets deleted either in 159 // the error check below or in ~Source() (since pNoDelete is false). 160 llvm::Module *module = managedModule.release(); 161 if (module == nullptr) { 162 return nullptr; 163 } 164 165 Source *result = CreateFromModule(pContext, pPath.c_str(), *module, 166 compilerVersion, optimizationLevel, 167 /* pNoDelete */false); 168 if (result == nullptr) { 169 delete module; 170 } 171 172 return result; 173} 174 175Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule, 176 const uint32_t compilerVersion, 177 const uint32_t optimizationLevel, 178 bool pNoDelete) { 179 std::string ErrorInfo; 180 llvm::raw_string_ostream ErrorStream(ErrorInfo); 181 pModule.materializeAll(); 182 if (llvm::verifyModule(pModule, &ErrorStream)) { 183 ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!", 184 ErrorStream.str().c_str()); 185 return nullptr; 186 } 187 188 Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete); 189 if (result == nullptr) { 190 ALOGE("Out of memory during Source object allocation for `%s'!", 191 pModule.getModuleIdentifier().c_str()); 192 } 193 helper_set_module_metadata_from_bitcode_wrapper(pModule, compilerVersion, optimizationLevel); 194 return result; 195} 196 197Source::Source(const char* name, BCCContext &pContext, llvm::Module &pModule, 198 bool pNoDelete) 199 : mName(name), mContext(pContext), mModule(&pModule), mMetadata(nullptr), 200 mNoDelete(pNoDelete), mIsModuleDestroyed(false) { 201 pContext.addSource(*this); 202} 203 204Source::~Source() { 205 mContext.removeSource(*this); 206 if (!mNoDelete && !mIsModuleDestroyed) 207 delete mModule; 208 delete mMetadata; 209} 210 211bool Source::merge(Source &pSource) { 212 // TODO(srhines): Add back logging of actual diagnostics from linking. 213 if (llvm::Linker::linkModules(*mModule, std::unique_ptr<llvm::Module>(&pSource.getModule())) != 0) { 214 ALOGE("Failed to link source `%s' with `%s'!", 215 getIdentifier().c_str(), pSource.getIdentifier().c_str()); 216 return false; 217 } 218 // pSource.getModule() is destroyed after linking. 219 pSource.markModuleDestroyed(); 220 221 return true; 222} 223 224const std::string &Source::getIdentifier() const { 225 return mModule->getModuleIdentifier(); 226} 227 228void Source::addBuildChecksumMetadata(const char *buildChecksum) const { 229 llvm::LLVMContext &context = mContext.mImpl->mLLVMContext; 230 llvm::MDString *val = llvm::MDString::get(context, buildChecksum); 231 llvm::NamedMDNode *node = 232 mModule->getOrInsertNamedMetadata("#rs_build_checksum"); 233 node->addOperand(llvm::MDNode::get(context, val)); 234} 235 236bool Source::getDebugInfoEnabled() const { 237 return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr; 238} 239 240bool Source::extractMetadata() { 241 mMetadata = new bcinfo::MetadataExtractor(mModule); 242 return mMetadata->extract(); 243} 244 245} // namespace bcc 246