blob: 63c4a5a181743566d7e4fec96536444fda9105cd [file] [log] [blame]
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -07001/*
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
Zonr Changc72c4dd2012-04-12 15:38:53 +080017#include "bcc/Source.h"
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070018
Jean-Luc Brouilleta2dd52f2017-02-16 20:57:26 -080019#include "Log.h"
20#include "bcc/BCCContext.h"
21
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070022#include <new>
23
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080024#include <llvm/ADT/STLExtras.h>
David Grosscf5afcb2017-03-20 15:23:26 -070025#include <llvm/ADT/StringExtras.h>
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070026#include <llvm/Bitcode/ReaderWriter.h>
Stephen Hinesb730e232013-01-09 15:31:36 -080027#include <llvm/IR/LLVMContext.h>
Stephen Hinesb730e232013-01-09 15:31:36 -080028#include <llvm/IR/Module.h>
Tim Murrayc2074ca2014-04-08 15:39:08 -070029#include <llvm/IR/Verifier.h>
30#include <llvm/Linker/Linker.h>
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070031#include <llvm/Support/MemoryBuffer.h>
Tim Murrayc2074ca2014-04-08 15:39:08 -070032#include "llvm/Support/raw_ostream.h"
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070033
David Grosscf5afcb2017-03-20 15:23:26 -070034#include "Assert.h"
35#include "bcinfo/BitcodeWrapper.h"
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080036#include "bcinfo/MetadataExtractor.h"
37
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070038#include "BCCContextImpl.h"
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070039
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,
Chris Wailes900c6c12014-08-13 15:40:00 -070045// return nullptr and will NOT take the ownership of pInput.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080046static inline std::unique_ptr<llvm::Module> helper_load_bitcode(llvm::LLVMContext &pContext,
Stephen Hines57936132014-11-25 17:54:59 -080047 std::unique_ptr<llvm::MemoryBuffer> &&pInput) {
Chih-Hung Hsieh121c92c2020-03-06 11:47:54 -080048 auto bufferId = pInput->getBufferIdentifier();
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080049 llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError
50 = llvm::getLazyBitcodeModule(std::move(pInput), pContext);
Stephen Hinesd0993af2014-07-15 16:49:25 -070051 if (std::error_code ec = moduleOrError.getError()) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070052 ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
Chih-Hung Hsieh121c92c2020-03-06 11:47:54 -080053 bufferId, ec.message().c_str());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070054 }
55
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080056 return std::move(moduleOrError.get());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070057}
58
David Grosscf5afcb2017-03-20 15:23:26 -070059static void helper_get_module_metadata_from_bitcode_wrapper(
60 uint32_t *compilerVersion, uint32_t *optimizationLevel,
61 const bcinfo::BitcodeWrapper &wrapper) {
62 *compilerVersion = wrapper.getCompilerVersion();
63 *optimizationLevel = wrapper.getOptimizationLevel();
64}
65
66static void helper_set_module_metadata_from_bitcode_wrapper(llvm::Module &module,
67 const uint32_t compilerVersion,
68 const uint32_t optimizationLevel) {
69 llvm::LLVMContext &llvmContext = module.getContext();
70
71 llvm::NamedMDNode *const wrapperMDNode =
72 module.getOrInsertNamedMetadata(bcinfo::MetadataExtractor::kWrapperMetadataName);
73 bccAssert(wrapperMDNode->getNumOperands() == 0); // expect to have just now created this node
74
75 llvm::SmallVector<llvm::Metadata *, 2> wrapperInfo = {
76 llvm::MDString::get(llvmContext, llvm::utostr(compilerVersion)),
77 llvm::MDString::get(llvmContext, llvm::utostr(optimizationLevel))
78 };
79
80 wrapperMDNode->addOperand(llvm::MDTuple::get(llvmContext, wrapperInfo));
81}
82
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070083} // end anonymous namespace
84
85namespace bcc {
86
David Grosscf5afcb2017-03-20 15:23:26 -070087unsigned Source::getCompilerVersion() const {
88 return bcinfo::MetadataExtractor(&getModule()).getCompilerVersion();
89}
90
91void Source::getWrapperInformation(unsigned *compilerVersion,
92 unsigned *optimizationLevel) const {
93 const bcinfo::MetadataExtractor &me = bcinfo::MetadataExtractor(&getModule());
94 *compilerVersion = me.getCompilerVersion();
95 *optimizationLevel = me.getOptimizationLevel();
96}
97
Stephen Hines06731a62013-02-12 19:29:42 -080098void Source::setModule(llvm::Module *pModule) {
99 if (!mNoDelete && (mModule != pModule)) delete mModule;
100 mModule = pModule;
101}
102
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700103Source *Source::CreateFromBuffer(BCCContext &pContext,
104 const char *pName,
105 const char *pBitcode,
106 size_t pBitcodeSize) {
107 llvm::StringRef input_data(pBitcode, pBitcodeSize);
Stephen Hines57936132014-11-25 17:54:59 -0800108 std::unique_ptr<llvm::MemoryBuffer> input_memory =
Shih-wei Liaoc996b872012-06-22 18:57:15 -0700109 llvm::MemoryBuffer::getMemBuffer(input_data, "", false);
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700110
Chris Wailes900c6c12014-08-13 15:40:00 -0700111 if (input_memory == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700112 ALOGE("Unable to load bitcode `%s' from buffer!", pName);
Chris Wailes900c6c12014-08-13 15:40:00 -0700113 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700114 }
115
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800116 auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext,
117 std::move(input_memory));
118
119 // Release the managed llvm::Module* since this object gets deleted either in
120 // the error check below or in ~Source() (since pNoDelete is false).
121 llvm::Module *module = managedModule.release();
Chris Wailes900c6c12014-08-13 15:40:00 -0700122 if (module == nullptr) {
Chris Wailes900c6c12014-08-13 15:40:00 -0700123 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700124 }
125
David Grosscf5afcb2017-03-20 15:23:26 -0700126 uint32_t compilerVersion, optimizationLevel;
127 helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel,
128 bcinfo::BitcodeWrapper(pBitcode, pBitcodeSize));
129 Source *result = CreateFromModule(pContext, pName, *module,
130 compilerVersion, optimizationLevel,
131 /* pNoDelete */false);
Chris Wailes900c6c12014-08-13 15:40:00 -0700132 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700133 delete module;
134 }
135
136 return result;
137}
138
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700139Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700140
Stephen Hinesd0993af2014-07-15 16:49:25 -0700141 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error =
142 llvm::MemoryBuffer::getFile(pPath);
143 if (mb_or_error.getError()) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700144 ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
Stephen Hinesd0993af2014-07-15 16:49:25 -0700145 mb_or_error.getError().message().c_str());
Chris Wailes900c6c12014-08-13 15:40:00 -0700146 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700147 }
Stephen Hinesd0993af2014-07-15 16:49:25 -0700148 std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700149
David Grosscf5afcb2017-03-20 15:23:26 -0700150 uint32_t compilerVersion, optimizationLevel;
151 helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel,
152 bcinfo::BitcodeWrapper(input_data->getBufferStart(),
153 input_data->getBufferSize()));
154
Stephen Hines57936132014-11-25 17:54:59 -0800155 std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release());
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800156 auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext,
157 std::move(input_memory));
158
159 // Release the managed llvm::Module* since this object gets deleted either in
160 // the error check below or in ~Source() (since pNoDelete is false).
161 llvm::Module *module = managedModule.release();
Chris Wailes900c6c12014-08-13 15:40:00 -0700162 if (module == nullptr) {
Chris Wailes900c6c12014-08-13 15:40:00 -0700163 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700164 }
165
David Grosscf5afcb2017-03-20 15:23:26 -0700166 Source *result = CreateFromModule(pContext, pPath.c_str(), *module,
167 compilerVersion, optimizationLevel,
168 /* pNoDelete */false);
Chris Wailes900c6c12014-08-13 15:40:00 -0700169 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700170 delete module;
171 }
172
173 return result;
174}
175
Yang Nia4ded132014-11-17 17:44:08 -0800176Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule,
David Grosscf5afcb2017-03-20 15:23:26 -0700177 const uint32_t compilerVersion,
178 const uint32_t optimizationLevel,
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700179 bool pNoDelete) {
Tobias Grosserb316f582013-08-14 18:52:58 -0700180 std::string ErrorInfo;
Tim Murrayc2074ca2014-04-08 15:39:08 -0700181 llvm::raw_string_ostream ErrorStream(ErrorInfo);
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800182 pModule.materializeAll();
Tim Murrayc2074ca2014-04-08 15:39:08 -0700183 if (llvm::verifyModule(pModule, &ErrorStream)) {
Tobias Grosserb316f582013-08-14 18:52:58 -0700184 ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!",
Tim Murrayc2074ca2014-04-08 15:39:08 -0700185 ErrorStream.str().c_str());
Chris Wailes900c6c12014-08-13 15:40:00 -0700186 return nullptr;
Tobias Grosserb316f582013-08-14 18:52:58 -0700187 }
188
Yang Nia4ded132014-11-17 17:44:08 -0800189 Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete);
Chris Wailes900c6c12014-08-13 15:40:00 -0700190 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700191 ALOGE("Out of memory during Source object allocation for `%s'!",
192 pModule.getModuleIdentifier().c_str());
193 }
David Grosscf5afcb2017-03-20 15:23:26 -0700194 helper_set_module_metadata_from_bitcode_wrapper(pModule, compilerVersion, optimizationLevel);
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700195 return result;
196}
197
Yang Nia4ded132014-11-17 17:44:08 -0800198Source::Source(const char* name, BCCContext &pContext, llvm::Module &pModule,
199 bool pNoDelete)
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800200 : mName(name), mContext(pContext), mModule(&pModule), mMetadata(nullptr),
201 mNoDelete(pNoDelete), mIsModuleDestroyed(false) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700202 pContext.addSource(*this);
203}
204
205Source::~Source() {
206 mContext.removeSource(*this);
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800207 if (!mNoDelete && !mIsModuleDestroyed)
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700208 delete mModule;
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800209 delete mMetadata;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700210}
211
Stephen Hines57936132014-11-25 17:54:59 -0800212bool Source::merge(Source &pSource) {
213 // TODO(srhines): Add back logging of actual diagnostics from linking.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800214 if (llvm::Linker::linkModules(*mModule, std::unique_ptr<llvm::Module>(&pSource.getModule())) != 0) {
Stephen Hines57936132014-11-25 17:54:59 -0800215 ALOGE("Failed to link source `%s' with `%s'!",
216 getIdentifier().c_str(), pSource.getIdentifier().c_str());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700217 return false;
218 }
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800219 // pSource.getModule() is destroyed after linking.
220 pSource.markModuleDestroyed();
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700221
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700222 return true;
223}
224
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700225const std::string &Source::getIdentifier() const {
226 return mModule->getModuleIdentifier();
227}
228
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800229void Source::addBuildChecksumMetadata(const char *buildChecksum) const {
230 llvm::LLVMContext &context = mContext.mImpl->mLLVMContext;
231 llvm::MDString *val = llvm::MDString::get(context, buildChecksum);
232 llvm::NamedMDNode *node =
233 mModule->getOrInsertNamedMetadata("#rs_build_checksum");
234 node->addOperand(llvm::MDNode::get(context, val));
235}
236
Dean De Leo09c7a412015-11-25 12:45:45 +0000237bool Source::getDebugInfoEnabled() const {
238 return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr;
239}
240
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800241bool Source::extractMetadata() {
242 mMetadata = new bcinfo::MetadataExtractor(mModule);
243 return mMetadata->extract();
244}
245
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700246} // namespace bcc