blob: d99eb10910b1d50d0e58a467ba419994a8291826 [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) {
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080048 llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError
49 = llvm::getLazyBitcodeModule(std::move(pInput), pContext);
Stephen Hinesd0993af2014-07-15 16:49:25 -070050 if (std::error_code ec = moduleOrError.getError()) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070051 ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
Tim Murrayc2074ca2014-04-08 15:39:08 -070052 pInput->getBufferIdentifier(), ec.message().c_str());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070053 }
54
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -080055 return std::move(moduleOrError.get());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070056}
57
David Grosscf5afcb2017-03-20 15:23:26 -070058static 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
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -070082} // end anonymous namespace
83
84namespace bcc {
85
David Grosscf5afcb2017-03-20 15:23:26 -070086unsigned 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
Stephen Hines06731a62013-02-12 19:29:42 -080097void Source::setModule(llvm::Module *pModule) {
98 if (!mNoDelete && (mModule != pModule)) delete mModule;
99 mModule = pModule;
100}
101
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700102Source *Source::CreateFromBuffer(BCCContext &pContext,
103 const char *pName,
104 const char *pBitcode,
105 size_t pBitcodeSize) {
106 llvm::StringRef input_data(pBitcode, pBitcodeSize);
Stephen Hines57936132014-11-25 17:54:59 -0800107 std::unique_ptr<llvm::MemoryBuffer> input_memory =
Shih-wei Liaoc996b872012-06-22 18:57:15 -0700108 llvm::MemoryBuffer::getMemBuffer(input_data, "", false);
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700109
Chris Wailes900c6c12014-08-13 15:40:00 -0700110 if (input_memory == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700111 ALOGE("Unable to load bitcode `%s' from buffer!", pName);
Chris Wailes900c6c12014-08-13 15:40:00 -0700112 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700113 }
114
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800115 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();
Chris Wailes900c6c12014-08-13 15:40:00 -0700121 if (module == nullptr) {
Chris Wailes900c6c12014-08-13 15:40:00 -0700122 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700123 }
124
David Grosscf5afcb2017-03-20 15:23:26 -0700125 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);
Chris Wailes900c6c12014-08-13 15:40:00 -0700131 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700132 delete module;
133 }
134
135 return result;
136}
137
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700138Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700139
Stephen Hinesd0993af2014-07-15 16:49:25 -0700140 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error =
141 llvm::MemoryBuffer::getFile(pPath);
142 if (mb_or_error.getError()) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700143 ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
Stephen Hinesd0993af2014-07-15 16:49:25 -0700144 mb_or_error.getError().message().c_str());
Chris Wailes900c6c12014-08-13 15:40:00 -0700145 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700146 }
Stephen Hinesd0993af2014-07-15 16:49:25 -0700147 std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700148
David Grosscf5afcb2017-03-20 15:23:26 -0700149 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
Stephen Hines57936132014-11-25 17:54:59 -0800154 std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release());
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800155 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();
Chris Wailes900c6c12014-08-13 15:40:00 -0700161 if (module == nullptr) {
Chris Wailes900c6c12014-08-13 15:40:00 -0700162 return nullptr;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700163 }
164
David Grosscf5afcb2017-03-20 15:23:26 -0700165 Source *result = CreateFromModule(pContext, pPath.c_str(), *module,
166 compilerVersion, optimizationLevel,
167 /* pNoDelete */false);
Chris Wailes900c6c12014-08-13 15:40:00 -0700168 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700169 delete module;
170 }
171
172 return result;
173}
174
Yang Nia4ded132014-11-17 17:44:08 -0800175Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule,
David Grosscf5afcb2017-03-20 15:23:26 -0700176 const uint32_t compilerVersion,
177 const uint32_t optimizationLevel,
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700178 bool pNoDelete) {
Tobias Grosserb316f582013-08-14 18:52:58 -0700179 std::string ErrorInfo;
Tim Murrayc2074ca2014-04-08 15:39:08 -0700180 llvm::raw_string_ostream ErrorStream(ErrorInfo);
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800181 pModule.materializeAll();
Tim Murrayc2074ca2014-04-08 15:39:08 -0700182 if (llvm::verifyModule(pModule, &ErrorStream)) {
Tobias Grosserb316f582013-08-14 18:52:58 -0700183 ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!",
Tim Murrayc2074ca2014-04-08 15:39:08 -0700184 ErrorStream.str().c_str());
Chris Wailes900c6c12014-08-13 15:40:00 -0700185 return nullptr;
Tobias Grosserb316f582013-08-14 18:52:58 -0700186 }
187
Yang Nia4ded132014-11-17 17:44:08 -0800188 Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete);
Chris Wailes900c6c12014-08-13 15:40:00 -0700189 if (result == nullptr) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700190 ALOGE("Out of memory during Source object allocation for `%s'!",
191 pModule.getModuleIdentifier().c_str());
192 }
David Grosscf5afcb2017-03-20 15:23:26 -0700193 helper_set_module_metadata_from_bitcode_wrapper(pModule, compilerVersion, optimizationLevel);
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700194 return result;
195}
196
Yang Nia4ded132014-11-17 17:44:08 -0800197Source::Source(const char* name, BCCContext &pContext, llvm::Module &pModule,
198 bool pNoDelete)
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800199 : mName(name), mContext(pContext), mModule(&pModule), mMetadata(nullptr),
200 mNoDelete(pNoDelete), mIsModuleDestroyed(false) {
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700201 pContext.addSource(*this);
202}
203
204Source::~Source() {
205 mContext.removeSource(*this);
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800206 if (!mNoDelete && !mIsModuleDestroyed)
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700207 delete mModule;
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800208 delete mMetadata;
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700209}
210
Stephen Hines57936132014-11-25 17:54:59 -0800211bool Source::merge(Source &pSource) {
212 // TODO(srhines): Add back logging of actual diagnostics from linking.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800213 if (llvm::Linker::linkModules(*mModule, std::unique_ptr<llvm::Module>(&pSource.getModule())) != 0) {
Stephen Hines57936132014-11-25 17:54:59 -0800214 ALOGE("Failed to link source `%s' with `%s'!",
215 getIdentifier().c_str(), pSource.getIdentifier().c_str());
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700216 return false;
217 }
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800218 // pSource.getModule() is destroyed after linking.
219 pSource.markModuleDestroyed();
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700220
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700221 return true;
222}
223
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700224const std::string &Source::getIdentifier() const {
225 return mModule->getModuleIdentifier();
226}
227
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800228void 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
Dean De Leo09c7a412015-11-25 12:45:45 +0000236bool Source::getDebugInfoEnabled() const {
237 return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr;
238}
239
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800240bool Source::extractMetadata() {
241 mMetadata = new bcinfo::MetadataExtractor(mModule);
242 return mMetadata->extract();
243}
244
Shih-wei Liaod2a5a0e2012-04-25 03:40:50 -0700245} // namespace bcc