Source.cpp revision 06731a6150ae8014d37258d5f32ef8bc14a3db63
1d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao/* 2d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * Copyright 2012, The Android Open Source Project 3d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * 4d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 5d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * you may not use this file except in compliance with the License. 6d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * You may obtain a copy of the License at 7d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * 8d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 9d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * 10d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * Unless required by applicable law or agreed to in writing, software 11d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS, 12d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * See the License for the specific language governing permissions and 14d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao * limitations under the License. 15d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao */ 16d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 17c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Source.h" 18d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 19d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <new> 20d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 21d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Bitcode/ReaderWriter.h> 22b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/LLVMContext.h> 23d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Linker.h> 24b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h> 25d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Support/MemoryBuffer.h> 26d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Support/system_error.h> 27d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 28c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/BCCContext.h" 29ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h" 30c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang 31d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include "BCCContextImpl.h" 32d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 33d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaonamespace { 34d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 35d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// Helper function to load the bitcode. This uses "bitcode lazy load" feature to 36d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// reduce the startup time. On success, return the LLVM module object created 37d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// and take the ownership of input memory buffer (i.e., pInput). On error, 38d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// return NULL and will NOT take the ownership of pInput. 39d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaostatic inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext, 40d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::MemoryBuffer *pInput) { 41d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao std::string error; 42d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Module *module = llvm::getLazyBitcodeModule(pInput, pContext, &error); 43d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 44d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (module == NULL) { 45d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Unable to parse the given bitcode file `%s'! (%s)", 46d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pInput->getBufferIdentifier(), error.c_str()); 47d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 48d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 49d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return module; 50d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 51d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 52d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} // end anonymous namespace 53d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 54d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaonamespace bcc { 55d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 5606731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hinesvoid Source::setModule(llvm::Module *pModule) { 5706731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines if (!mNoDelete && (mModule != pModule)) delete mModule; 5806731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines mModule = pModule; 5906731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines} 6006731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines 61d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateFromBuffer(BCCContext &pContext, 62d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao const char *pName, 63d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao const char *pBitcode, 64d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao size_t pBitcodeSize) { 65d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::StringRef input_data(pBitcode, pBitcodeSize); 66d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::MemoryBuffer *input_memory = 67c996b870ae40603b477a8d7a50f461b82389aaf1Shih-wei Liao llvm::MemoryBuffer::getMemBuffer(input_data, "", false); 68d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 69d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (input_memory == NULL) { 70d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Unable to load bitcode `%s' from buffer!", pName); 71d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return NULL; 72d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 73d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 74d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 75d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao input_memory); 76d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (module == NULL) { 77d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete input_memory; 78d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return NULL; 79d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 80d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 81d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 82d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (result == NULL) { 83d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete module; 84d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 85d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 86d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 87d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 88d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 89d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) { 90d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::OwningPtr<llvm::MemoryBuffer> input_data; 91d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 92d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::error_code ec = llvm::MemoryBuffer::getFile(pPath, input_data); 93d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (ec != llvm::error_code::success()) { 94d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(), 95d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ec.message().c_str()); 96d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return NULL; 97d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 98d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 99d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::MemoryBuffer *input_memory = input_data.take(); 100d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 101d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao input_memory); 102d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (module == NULL) { 103d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete input_memory; 104d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return NULL; 105d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 106d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 107d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 108d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (result == NULL) { 109d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete module; 110d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 111d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 112d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 113d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 114d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 1156202dda52b7898340aac05e73adebc4fb9199f4dShih-wei LiaoSource *Source::CreateFromFd(BCCContext &pContext, int pFd) { 1166202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao llvm::OwningPtr<llvm::MemoryBuffer> input_data; 1176202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1186202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao llvm::error_code ec = 1196202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao llvm::MemoryBuffer::getOpenFile(pFd, /* Filename */"", input_data); 1206202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1216202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao if (ec != llvm::error_code::success()) { 1226202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao ALOGE("Failed to load bitcode from file descriptor %d! (%s)", 1236202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao pFd, ec.message().c_str()); 1246202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao return NULL; 1256202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao } 1266202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1276202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao llvm::MemoryBuffer *input_memory = input_data.take(); 1286202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext, 1296202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao input_memory); 1306202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao if (module == NULL) { 1316202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao delete input_memory; 1326202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao return NULL; 1336202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao } 1346202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1356202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 1366202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao if (result == NULL) { 1376202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao delete module; 1386202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao } 1396202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1406202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao return result; 1416202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao} 142d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 143d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateFromModule(BCCContext &pContext, llvm::Module &pModule, 144d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao bool pNoDelete) { 145d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao Source *result = new (std::nothrow) Source(pContext, pModule, pNoDelete); 146d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (result == NULL) { 147d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Out of memory during Source object allocation for `%s'!", 148d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pModule.getModuleIdentifier().c_str()); 149d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 150d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 151d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 152d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 153d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource::Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete) 154d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao : mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) { 155d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pContext.addSource(*this); 156d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 157d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 158d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource::~Source() { 159d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao mContext.removeSource(*this); 160d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (!mNoDelete) 161d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete mModule; 162d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 163d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 164d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaobool Source::merge(Source &pSource, bool pPreserveSource) { 165d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao std::string error; 166d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Linker::LinkerMode mode = 167d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ((pPreserveSource) ? llvm::Linker::PreserveSource : 168d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Linker::DestroySource); 169d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 170d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (llvm::Linker::LinkModules(mModule, &pSource.getModule(), 171d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao mode, &error) != 0) { 172d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Failed to link source `%s' with `%s' (%s)!", 173d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao getIdentifier().c_str(), 174d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pSource.getIdentifier().c_str(), 175d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao error.c_str()); 176d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return false; 177d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 178d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 179d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (!pPreserveSource) { 180d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pSource.mNoDelete = true; 181d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete &pSource; 182d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 183d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 184d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return true; 185d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 186d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 187d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) { 188d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao // Create an empty module 189d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Module *module = 190d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext); 191d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 192d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (module == NULL) { 193d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str()); 194d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return NULL; 195d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 196d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 197d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false); 198d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao if (result == NULL) { 199d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete module; 200d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 201d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 202d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 203d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 204d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 205d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaoconst std::string &Source::getIdentifier() const { 206d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return mModule->getModuleIdentifier(); 207d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 208d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 209d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} // namespace bcc 210