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