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 218e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar#include <llvm/ADT/STLExtras.h> 22d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Bitcode/ReaderWriter.h> 23b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/LLVMContext.h> 24b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h> 25c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray#include <llvm/IR/Verifier.h> 26c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray#include <llvm/Linker/Linker.h> 27d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include <llvm/Support/MemoryBuffer.h> 28c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray#include "llvm/Support/raw_ostream.h" 29d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 30c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/BCCContext.h" 31ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h" 32c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang 338e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar#include "bcinfo/MetadataExtractor.h" 348e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar 35d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao#include "BCCContextImpl.h" 36d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 37d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaonamespace { 38d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 39d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// Helper function to load the bitcode. This uses "bitcode lazy load" feature to 40d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// reduce the startup time. On success, return the LLVM module object created 41d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao// and take the ownership of input memory buffer (i.e., pInput). On error, 42900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes// return nullptr and will NOT take the ownership of pInput. 438e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainarstatic inline std::unique_ptr<llvm::Module> helper_load_bitcode(llvm::LLVMContext &pContext, 44579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines std::unique_ptr<llvm::MemoryBuffer> &&pInput) { 458e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError 468e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar = llvm::getLazyBitcodeModule(std::move(pInput), pContext); 47d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines if (std::error_code ec = moduleOrError.getError()) { 48d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Unable to parse the given bitcode file `%s'! (%s)", 49c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray pInput->getBufferIdentifier(), ec.message().c_str()); 50d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 51d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 528e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar return std::move(moduleOrError.get()); 53d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 54d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 55d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} // end anonymous namespace 56d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 57d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaonamespace bcc { 58d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 5906731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hinesvoid Source::setModule(llvm::Module *pModule) { 6006731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines if (!mNoDelete && (mModule != pModule)) delete mModule; 6106731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines mModule = pModule; 6206731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines} 6306731a6150ae8014d37258d5f32ef8bc14a3db63Stephen Hines 64d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateFromBuffer(BCCContext &pContext, 65d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao const char *pName, 66d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao const char *pBitcode, 67d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao size_t pBitcodeSize) { 68d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::StringRef input_data(pBitcode, pBitcodeSize); 69579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines std::unique_ptr<llvm::MemoryBuffer> input_memory = 70c996b870ae40603b477a8d7a50f461b82389aaf1Shih-wei Liao llvm::MemoryBuffer::getMemBuffer(input_data, "", false); 71d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 72900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (input_memory == nullptr) { 73d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Unable to load bitcode `%s' from buffer!", pName); 74900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 75d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 76d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 778e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext, 788e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar std::move(input_memory)); 798e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar 808e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar // Release the managed llvm::Module* since this object gets deleted either in 818e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar // the error check below or in ~Source() (since pNoDelete is false). 828e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar llvm::Module *module = managedModule.release(); 83900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (module == nullptr) { 84900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 85d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 86d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 87a4ded1373d7ad3e503f186e65bccf94126a0f020Yang Ni Source *result = CreateFromModule(pContext, pName, *module, /* pNoDelete */false); 88900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (result == nullptr) { 89d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete module; 90d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 91d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 92d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 93d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 94d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 95d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) { 96d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 97d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error = 98d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines llvm::MemoryBuffer::getFile(pPath); 99d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines if (mb_or_error.getError()) { 100d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(), 101d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines mb_or_error.getError().message().c_str()); 102900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 103d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 104d0993af5b1337f8186dd9aedea2e138a919e02e9Stephen Hines std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get()); 105d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 106579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release()); 1078e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext, 1088e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar std::move(input_memory)); 1098e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar 1108e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar // Release the managed llvm::Module* since this object gets deleted either in 1118e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar // the error check below or in ~Source() (since pNoDelete is false). 1128e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar llvm::Module *module = managedModule.release(); 113900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (module == nullptr) { 114900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 1156202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao } 1166202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 117a4ded1373d7ad3e503f186e65bccf94126a0f020Yang Ni Source *result = CreateFromModule(pContext, pPath.c_str(), *module, /* pNoDelete */false); 118900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (result == nullptr) { 1196202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao delete module; 1206202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao } 1216202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao 1226202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao return result; 1236202dda52b7898340aac05e73adebc4fb9199f4dShih-wei Liao} 124d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 125a4ded1373d7ad3e503f186e65bccf94126a0f020Yang NiSource *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule, 126d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao bool pNoDelete) { 127b316f58fd790ad302b72f569af3e89734ae09db7Tobias Grosser std::string ErrorInfo; 128c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray llvm::raw_string_ostream ErrorStream(ErrorInfo); 1298e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar pModule.materializeAll(); 130c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray if (llvm::verifyModule(pModule, &ErrorStream)) { 131b316f58fd790ad302b72f569af3e89734ae09db7Tobias Grosser ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!", 132c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray ErrorStream.str().c_str()); 133900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 134b316f58fd790ad302b72f569af3e89734ae09db7Tobias Grosser } 135b316f58fd790ad302b72f569af3e89734ae09db7Tobias Grosser 136a4ded1373d7ad3e503f186e65bccf94126a0f020Yang Ni Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete); 137900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (result == nullptr) { 138d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Out of memory during Source object allocation for `%s'!", 139d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pModule.getModuleIdentifier().c_str()); 140d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 141d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 142d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 143d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 144a4ded1373d7ad3e503f186e65bccf94126a0f020Yang NiSource::Source(const char* name, BCCContext &pContext, llvm::Module &pModule, 145a4ded1373d7ad3e503f186e65bccf94126a0f020Yang Ni bool pNoDelete) 1468e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar : mName(name), mContext(pContext), mModule(&pModule), mMetadata(nullptr), 1478e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar mNoDelete(pNoDelete), mIsModuleDestroyed(false) { 148d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao pContext.addSource(*this); 149d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 150d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 151d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource::~Source() { 152d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao mContext.removeSource(*this); 1538e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar if (!mNoDelete && !mIsModuleDestroyed) 154d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete mModule; 1558e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar delete mMetadata; 156d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 157d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 158579361346abc6696c805e3904a18178ebce4e4a3Stephen Hinesbool Source::merge(Source &pSource) { 159579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines // TODO(srhines): Add back logging of actual diagnostics from linking. 1608e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar if (llvm::Linker::linkModules(*mModule, std::unique_ptr<llvm::Module>(&pSource.getModule())) != 0) { 161579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines ALOGE("Failed to link source `%s' with `%s'!", 162579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines getIdentifier().c_str(), pSource.getIdentifier().c_str()); 163d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return false; 164d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 1658e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar // pSource.getModule() is destroyed after linking. 1668e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar pSource.markModuleDestroyed(); 167d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 168d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return true; 169d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 170d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 171d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei LiaoSource *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) { 172d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao // Create an empty module 173d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao llvm::Module *module = 174d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext); 175d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 176900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (module == nullptr) { 177d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str()); 178900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes return nullptr; 179d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 180d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 181a4ded1373d7ad3e503f186e65bccf94126a0f020Yang Ni Source *result = CreateFromModule(pContext, pName.c_str(), *module, /* pNoDelete */false); 182900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes if (result == nullptr) { 183d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao delete module; 184d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao } 185d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 186d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return result; 187d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 188d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 189d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liaoconst std::string &Source::getIdentifier() const { 190d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao return mModule->getModuleIdentifier(); 191d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} 192d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao 19351ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainarvoid Source::addBuildChecksumMetadata(const char *buildChecksum) const { 19451ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar llvm::LLVMContext &context = mContext.mImpl->mLLVMContext; 19551ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar llvm::MDString *val = llvm::MDString::get(context, buildChecksum); 19651ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar llvm::NamedMDNode *node = 19751ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar mModule->getOrInsertNamedMetadata("#rs_build_checksum"); 19851ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar node->addOperand(llvm::MDNode::get(context, val)); 19951ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar} 20051ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar 20109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leobool Source::getDebugInfoEnabled() const { 20209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr; 20309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo} 20409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo 2058e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainarbool Source::extractMetadata() { 2068e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar mMetadata = new bcinfo::MetadataExtractor(mModule); 2078e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar return mMetadata->extract(); 2088e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar} 2098e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar 210d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao} // namespace bcc 211