blob: 21beaa28bb1898eb52bf42461f8702ea597c90e7 [file] [log] [blame]
Zonr Chang0fffa7e2012-04-12 19:43:53 +08001/*
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
Stephen Hinese198abe2012-07-27 18:05:41 -070017#include "bcc/Renderscript/RSCompilerDriver.h"
Zonr Chang0fffa7e2012-04-12 19:43:53 +080018
Yang Nia4ded132014-11-17 17:44:08 -080019#include "llvm/IR/AssemblyAnnotationWriter.h"
Tobias Grosser7b980e12013-06-20 10:12:13 -070020#include <llvm/IR/Module.h>
Yang Ni0ab50b82015-02-16 12:31:56 -080021#include "llvm/Linker/Linker.h"
Stephen Hinesad694762013-04-29 18:59:47 -070022#include <llvm/Support/CommandLine.h>
Stephen Hinesb10c3a72013-08-07 23:15:22 -070023#include <llvm/Support/Path.h>
Tobias Grosser7b980e12013-06-20 10:12:13 -070024#include <llvm/Support/raw_ostream.h>
Shih-wei Liao7bcec852012-04-25 04:07:09 -070025
26#include "bcinfo/BitcodeWrapper.h"
Yang Ni0ab50b82015-02-16 12:31:56 -080027#include "bcc/Assert.h"
Yang Nia4ded132014-11-17 17:44:08 -080028#include "bcc/BCCContext.h"
Stephen Hines47f0d5a2013-06-05 00:27:38 -070029#include "bcc/Compiler.h"
Stephen Hinesbde1a252014-05-15 18:02:33 -070030#include "bcc/Config/Config.h"
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -070031#include "bcc/Renderscript/RSInfo.h"
Stephen Hinese198abe2012-07-27 18:05:41 -070032#include "bcc/Renderscript/RSScript.h"
Yang Nia4ded132014-11-17 17:44:08 -080033#include "bcc/Renderscript/RSScriptGroupFusion.h"
Zonr Changc72c4dd2012-04-12 15:38:53 +080034#include "bcc/Support/CompilerConfig.h"
Shih-wei Liao7bcec852012-04-25 04:07:09 -070035#include "bcc/Source.h"
Zonr Changc72c4dd2012-04-12 15:38:53 +080036#include "bcc/Support/FileMutex.h"
Zonr Changef73a242012-04-12 16:44:01 +080037#include "bcc/Support/Log.h"
Zonr Changc72c4dd2012-04-12 15:38:53 +080038#include "bcc/Support/InputFile.h"
39#include "bcc/Support/Initialization.h"
Shih-wei Liao7bcec852012-04-25 04:07:09 -070040#include "bcc/Support/Sha1Util.h"
Zonr Changc72c4dd2012-04-12 15:38:53 +080041#include "bcc/Support/OutputFile.h"
Zonr Chang0fffa7e2012-04-12 19:43:53 +080042
Yang Ni0ab50b82015-02-16 12:31:56 -080043#include <sstream>
Yang Nia4ded132014-11-17 17:44:08 -080044#include <string>
45
Nick Kralevichb81d6972013-05-21 16:52:35 -070046#ifdef HAVE_ANDROID_OS
Zonr Chang0fffa7e2012-04-12 19:43:53 +080047#include <cutils/properties.h>
Nick Kralevichb81d6972013-05-21 16:52:35 -070048#endif
Shih-wei Liao7bcec852012-04-25 04:07:09 -070049#include <utils/StopWatch.h>
Zonr Chang0fffa7e2012-04-12 19:43:53 +080050
51using namespace bcc;
52
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -070053// Get the build fingerprint of the Android device we are running on.
54static std::string getBuildFingerPrint() {
55#ifdef HAVE_ANDROID_OS
56 char fingerprint[PROPERTY_VALUE_MAX];
57 property_get("ro.build.fingerprint", fingerprint, "");
58 return fingerprint;
59#else
60 return "HostBuild";
61#endif
62}
63
Stephen Hines3ab9da12013-02-01 18:39:15 -080064RSCompilerDriver::RSCompilerDriver(bool pUseCompilerRT) :
Chris Wailes900c6c12014-08-13 15:40:00 -070065 mConfig(nullptr), mCompiler(), mDebugContext(false),
66 mLinkRuntimeCallback(nullptr), mEnableGlobalMerge(true) {
Zonr Chang0fffa7e2012-04-12 19:43:53 +080067 init::Initialize();
Zonr Chang0fffa7e2012-04-12 19:43:53 +080068}
69
70RSCompilerDriver::~RSCompilerDriver() {
71 delete mConfig;
72}
73
Zonr Chang0fffa7e2012-04-12 19:43:53 +080074
Stephen Hinesbde1a252014-05-15 18:02:33 -070075#if defined(PROVIDE_ARM_CODEGEN)
Stephen Hinesad694762013-04-29 18:59:47 -070076extern llvm::cl::opt<bool> EnableGlobalMerge;
Stephen Hinesc06cd062013-07-12 10:51:29 -070077#endif
78
Zonr Chang0fffa7e2012-04-12 19:43:53 +080079bool RSCompilerDriver::setupConfig(const RSScript &pScript) {
80 bool changed = false;
81
82 const llvm::CodeGenOpt::Level script_opt_level =
83 static_cast<llvm::CodeGenOpt::Level>(pScript.getOptimizationLevel());
84
Stephen Hinesbde1a252014-05-15 18:02:33 -070085#if defined(PROVIDE_ARM_CODEGEN)
Stephen Hines045558b2014-02-18 14:07:15 -080086 EnableGlobalMerge = mEnableGlobalMerge;
87#endif
88
Chris Wailes900c6c12014-08-13 15:40:00 -070089 if (mConfig != nullptr) {
Zonr Chang0fffa7e2012-04-12 19:43:53 +080090 // Renderscript bitcode may have their optimization flag configuration
91 // different than the previous run of RS compilation.
92 if (mConfig->getOptimizationLevel() != script_opt_level) {
93 mConfig->setOptimizationLevel(script_opt_level);
94 changed = true;
95 }
96 } else {
97 // Haven't run the compiler ever.
Stephen Hinesbde1a252014-05-15 18:02:33 -070098 mConfig = new (std::nothrow) CompilerConfig(DEFAULT_TARGET_TRIPLE_STRING);
Chris Wailes900c6c12014-08-13 15:40:00 -070099 if (mConfig == nullptr) {
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800100 // Return false since mConfig remains NULL and out-of-memory.
101 return false;
102 }
103 mConfig->setOptimizationLevel(script_opt_level);
104 changed = true;
105 }
106
Stephen Hinesbde1a252014-05-15 18:02:33 -0700107#if defined(PROVIDE_ARM_CODEGEN)
Chris Wailes900c6c12014-08-13 15:40:00 -0700108 assert((pScript.getInfo() != nullptr) && "NULL RS info!");
Stephen Hinesbde1a252014-05-15 18:02:33 -0700109 bool script_full_prec = (pScript.getInfo()->getFloatPrecisionRequirement() ==
110 RSInfo::FP_Full);
111 if (mConfig->getFullPrecision() != script_full_prec) {
112 mConfig->setFullPrecision(script_full_prec);
113 changed = true;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800114 }
115#endif
116
117 return changed;
118}
119
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700120Compiler::ErrorCode RSCompilerDriver::compileScript(RSScript& pScript, const char* pScriptName,
121 const char* pOutputPath,
122 const char* pRuntimePath,
123 const RSInfo::DependencyHashTy& pSourceHash,
124 const char* compileCommandLineToEmbed,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800125 const char* pBuildChecksum,
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700126 bool saveInfoFile, bool pDumpIR) {
127 // android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800128
129 // embed build checksum metadata into the source
130 if (pBuildChecksum != nullptr && strlen(pBuildChecksum) > 0) {
131 pScript.getSource().addBuildChecksumMetadata(pBuildChecksum);
132 }
133
Chris Wailes900c6c12014-08-13 15:40:00 -0700134 RSInfo *info = nullptr;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800135
136 //===--------------------------------------------------------------------===//
137 // Extract RS-specific information from source bitcode.
138 //===--------------------------------------------------------------------===//
139 // RS info may contains configuration (such as #optimization_level) to the
140 // compiler therefore it should be extracted before compilation.
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700141 info = RSInfo::ExtractFromSource(pScript.getSource(), pSourceHash, compileCommandLineToEmbed,
142 getBuildFingerPrint().c_str());
Chris Wailes900c6c12014-08-13 15:40:00 -0700143 if (info == nullptr) {
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700144 return Compiler::kErrInvalidSource;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800145 }
146
147 //===--------------------------------------------------------------------===//
148 // Associate script with its info
149 //===--------------------------------------------------------------------===//
150 // This is required since RS compiler may need information in the info file
151 // to do some transformation (e.g., expand foreach-able function.)
152 pScript.setInfo(info);
153
154 //===--------------------------------------------------------------------===//
Stephen Hinese198abe2012-07-27 18:05:41 -0700155 // Link RS script with Renderscript runtime.
Shih-wei Liaoba420642012-06-30 11:27:37 -0700156 //===--------------------------------------------------------------------===//
Stephen Hines331310e2012-10-26 19:27:55 -0700157 if (!RSScript::LinkRuntime(pScript, pRuntimePath)) {
Stephen Hinese198abe2012-07-27 18:05:41 -0700158 ALOGE("Failed to link script '%s' with Renderscript runtime!", pScriptName);
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700159 return Compiler::kErrInvalidSource;
Shih-wei Liaoba420642012-06-30 11:27:37 -0700160 }
161
Stephen Hines01f05d42013-05-31 20:51:27 -0700162 {
Stephen Hines07843652013-08-15 15:41:47 -0700163 // FIXME(srhines): Windows compilation can't use locking like this, but
164 // we also don't need to worry about concurrent writers of the same file.
Stephen Hinesd7a95262013-08-08 16:03:19 -0700165#ifndef USE_MINGW
Stephen Hines07843652013-08-15 15:41:47 -0700166 //===------------------------------------------------------------------===//
Stephen Hines01f05d42013-05-31 20:51:27 -0700167 // Acquire the write lock for writing output object file.
Stephen Hines07843652013-08-15 15:41:47 -0700168 //===------------------------------------------------------------------===//
Stephen Hines01f05d42013-05-31 20:51:27 -0700169 FileMutex<FileBase::kWriteLock> write_output_mutex(pOutputPath);
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800170
Stephen Hines01f05d42013-05-31 20:51:27 -0700171 if (write_output_mutex.hasError() || !write_output_mutex.lock()) {
172 ALOGE("Unable to acquire the lock for writing %s! (%s)",
173 pOutputPath, write_output_mutex.getErrorMessage().c_str());
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700174 return Compiler::kErrInvalidSource;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800175 }
Stephen Hinesd7a95262013-08-08 16:03:19 -0700176#endif
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800177
Stephen Hines01f05d42013-05-31 20:51:27 -0700178 // Open the output file for write.
Stephen Hinesacf9c9e2013-09-26 16:32:31 -0700179 OutputFile output_file(pOutputPath,
180 FileBase::kTruncate | FileBase::kBinary);
Stephen Hines01f05d42013-05-31 20:51:27 -0700181
182 if (output_file.hasError()) {
183 ALOGE("Unable to open %s for write! (%s)", pOutputPath,
184 output_file.getErrorMessage().c_str());
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700185 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700186 }
187
188 // Setup the config to the compiler.
189 bool compiler_need_reconfigure = setupConfig(pScript);
190
Chris Wailes900c6c12014-08-13 15:40:00 -0700191 if (mConfig == nullptr) {
Stephen Hines01f05d42013-05-31 20:51:27 -0700192 ALOGE("Failed to setup config for RS compiler to compile %s!",
193 pOutputPath);
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700194 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700195 }
196
197 if (compiler_need_reconfigure) {
198 Compiler::ErrorCode err = mCompiler.config(*mConfig);
199 if (err != Compiler::kSuccess) {
200 ALOGE("Failed to config the RS compiler for %s! (%s)",pOutputPath,
201 Compiler::GetErrorString(err));
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700202 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700203 }
204 }
205
Chris Wailes900c6c12014-08-13 15:40:00 -0700206 OutputFile *ir_file = nullptr;
207 llvm::raw_fd_ostream *IRStream = nullptr;
Tobias Grosser27fb7ed2013-06-21 18:34:56 -0700208 if (pDumpIR) {
Chris Wailes35978e72014-08-11 14:01:47 -0700209 std::string path(pOutputPath);
Tobias Grosser27fb7ed2013-06-21 18:34:56 -0700210 path.append(".ll");
Chris Wailes35978e72014-08-11 14:01:47 -0700211 ir_file = new OutputFile(path.c_str(), FileBase::kTruncate);
Tobias Grosser27fb7ed2013-06-21 18:34:56 -0700212 IRStream = ir_file->dup();
213 }
214
Stephen Hines01f05d42013-05-31 20:51:27 -0700215 // Run the compiler.
Chris Wailes35978e72014-08-11 14:01:47 -0700216 Compiler::ErrorCode compile_result =
217 mCompiler.compile(pScript, output_file, IRStream);
Tobias Grosser27fb7ed2013-06-21 18:34:56 -0700218
219 if (ir_file) {
220 ir_file->close();
221 delete ir_file;
222 }
Stephen Hines01f05d42013-05-31 20:51:27 -0700223
224 if (compile_result != Compiler::kSuccess) {
225 ALOGE("Unable to compile the source to file %s! (%s)", pOutputPath,
226 Compiler::GetErrorString(compile_result));
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700227 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700228 }
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800229 }
230
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700231 if (saveInfoFile) {
Chris Wailes35978e72014-08-11 14:01:47 -0700232 std::string info_path = RSInfo::GetPath(pOutputPath);
233 OutputFile info_file(info_path.c_str(), FileBase::kTruncate);
Stephen Hines01f05d42013-05-31 20:51:27 -0700234
235 if (info_file.hasError()) {
236 ALOGE("Failed to open the info file %s for write! (%s)",
Chris Wailes35978e72014-08-11 14:01:47 -0700237 info_path.c_str(), info_file.getErrorMessage().c_str());
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700238 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700239 }
240
Chris Wailes35978e72014-08-11 14:01:47 -0700241 FileMutex<FileBase::kWriteLock> write_info_mutex(info_path.c_str());
Stephen Hines01f05d42013-05-31 20:51:27 -0700242 if (write_info_mutex.hasError() || !write_info_mutex.lock()) {
243 ALOGE("Unable to acquire the lock for writing %s! (%s)",
Chris Wailes35978e72014-08-11 14:01:47 -0700244 info_path.c_str(), write_info_mutex.getErrorMessage().c_str());
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700245 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700246 }
247
248 // Perform the write.
249 if (!info->write(info_file)) {
Chris Wailes35978e72014-08-11 14:01:47 -0700250 ALOGE("Failed to sync the RS info file %s!", info_path.c_str());
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700251 return Compiler::kErrInvalidSource;
Stephen Hines01f05d42013-05-31 20:51:27 -0700252 }
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800253 }
254
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700255 return Compiler::kSuccess;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800256}
257
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700258bool RSCompilerDriver::build(BCCContext &pContext,
259 const char *pCacheDir,
260 const char *pResName,
261 const char *pBitcode,
262 size_t pBitcodeSize,
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700263 const char *commandLine,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800264 const char *pBuildChecksum,
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700265 const char *pRuntimePath,
Tobias Grosser7b980e12013-06-20 10:12:13 -0700266 RSLinkRuntimeCallback pLinkRuntimeCallback,
267 bool pDumpIR) {
Tim Murrayc89f78b2013-05-09 11:57:12 -0700268 // android::StopWatch build_time("bcc: RSCompilerDriver::build time");
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700269 //===--------------------------------------------------------------------===//
270 // Check parameters.
271 //===--------------------------------------------------------------------===//
Chris Wailes900c6c12014-08-13 15:40:00 -0700272 if ((pCacheDir == nullptr) || (pResName == nullptr)) {
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700273 ALOGE("Invalid parameter passed to RSCompilerDriver::build()! (cache dir: "
274 "%s, resource name: %s)", ((pCacheDir) ? pCacheDir : "(null)"),
275 ((pResName) ? pResName : "(null)"));
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700276 return false;
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700277 }
278
Chris Wailes900c6c12014-08-13 15:40:00 -0700279 if ((pBitcode == nullptr) || (pBitcodeSize <= 0)) {
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700280 ALOGE("No bitcode supplied! (bitcode: %p, size of bitcode: %u)",
281 pBitcode, static_cast<unsigned>(pBitcodeSize));
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700282 return false;
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700283 }
284
285 //===--------------------------------------------------------------------===//
286 // Prepare dependency information.
287 //===--------------------------------------------------------------------===//
Jean-Luc Brouilletc5e607a2014-06-18 18:14:02 -0700288 uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700289 Sha1Util::GetSHA1DigestFromBuffer(bitcode_sha1, pBitcode, pBitcodeSize);
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700290
291 //===--------------------------------------------------------------------===//
292 // Construct output path.
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700293 // {pCacheDir}/{pResName}.o
Stephen Hinesb10c3a72013-08-07 23:15:22 -0700294 //===--------------------------------------------------------------------===//
295 llvm::SmallString<80> output_path(pCacheDir);
296 llvm::sys::path::append(output_path, pResName);
297 llvm::sys::path::replace_extension(output_path, ".o");
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700298
299 //===--------------------------------------------------------------------===//
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700300 // Load the bitcode and create script.
301 //===--------------------------------------------------------------------===//
302 Source *source = Source::CreateFromBuffer(pContext, pResName,
303 pBitcode, pBitcodeSize);
Chris Wailes900c6c12014-08-13 15:40:00 -0700304 if (source == nullptr) {
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700305 return false;
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700306 }
307
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700308 RSScript script(*source);
Stephen Hinesc3437f02014-01-30 17:57:21 -0800309 if (pLinkRuntimeCallback) {
310 setLinkRuntimeCallback(pLinkRuntimeCallback);
311 }
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700312
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700313 script.setLinkRuntimeCallback(getLinkRuntimeCallback());
Stephen Hines06731a62013-02-12 19:29:42 -0800314
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700315 // Read information from bitcode wrapper.
316 bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700317 script.setCompilerVersion(wrapper.getCompilerVersion());
318 script.setOptimizationLevel(static_cast<RSScript::OptimizationLevel>(
319 wrapper.getOptimizationLevel()));
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700320
321 //===--------------------------------------------------------------------===//
322 // Compile the script
323 //===--------------------------------------------------------------------===//
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700324 Compiler::ErrorCode status = compileScript(script, pResName,
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700325 output_path.c_str(),
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700326 pRuntimePath, bitcode_sha1, commandLine,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800327 pBuildChecksum, true, pDumpIR);
Shih-wei Liao7bcec852012-04-25 04:07:09 -0700328
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700329 return status == Compiler::kSuccess;
Zonr Chang0fffa7e2012-04-12 19:43:53 +0800330}
Stephen Hines331310e2012-10-26 19:27:55 -0700331
Yang Nia4ded132014-11-17 17:44:08 -0800332bool RSCompilerDriver::buildScriptGroup(
Yang Ni0ab50b82015-02-16 12:31:56 -0800333 BCCContext& Context, const char* pOutputFilepath, const char* pRuntimePath,
334 bool dumpIR, const std::vector<Source*>& sources,
335 const std::list<std::list<std::pair<int, int>>>& toFuse,
336 const std::list<std::string>& fused,
337 const std::list<std::list<std::pair<int, int>>>& invokes,
338 const std::list<std::string>& invokeBatchNames) {
339 // ---------------------------------------------------------------------------
340 // Link all input modules into a single module
341 // ---------------------------------------------------------------------------
342
343 llvm::LLVMContext& context = Context.getLLVMContext();
344 llvm::Module module("Merged Script Group", context);
345
346 llvm::Linker linker(&module);
347 for (Source* source : sources) {
348 if (linker.linkInModule(&source->getModule())) {
349 ALOGE("Linking for module in source failed.");
350 return false;
351 }
Yang Nia4ded132014-11-17 17:44:08 -0800352 }
353
Yang Ni0ab50b82015-02-16 12:31:56 -0800354 // ---------------------------------------------------------------------------
355 // Create fused kernels
356 // ---------------------------------------------------------------------------
357
358 auto inputIter = toFuse.begin();
359 for (const std::string& nameOfFused : fused) {
360 auto inputKernels = *inputIter++;
361 std::vector<Source*> sourcesToFuse;
362 std::vector<int> slots;
363
364 for (auto p : inputKernels) {
365 sourcesToFuse.push_back(sources[p.first]);
366 slots.push_back(p.second);
367 }
368
369 if (!fuseKernels(Context, sourcesToFuse, slots, nameOfFused, &module)) {
370 return false;
371 }
372 }
373
374 // ---------------------------------------------------------------------------
375 // Rename invokes
376 // ---------------------------------------------------------------------------
377
378 auto invokeIter = invokes.begin();
379 for (const std::string& newName : invokeBatchNames) {
380 auto inputInvoke = *invokeIter++;
381 auto p = inputInvoke.front();
382 Source* source = sources[p.first];
383 int slot = p.second;
384
385 if (!renameInvoke(Context, source, slot, newName, &module)) {
386 return false;
387 }
388 }
389
390 // ---------------------------------------------------------------------------
391 // Compile the new module with fused kernels
392 // ---------------------------------------------------------------------------
393
Yang Nia4ded132014-11-17 17:44:08 -0800394 const std::unique_ptr<Source> source(
Yang Ni0ab50b82015-02-16 12:31:56 -0800395 Source::CreateFromModule(Context, pOutputFilepath, module, true));
Yang Nia4ded132014-11-17 17:44:08 -0800396 RSScript script(*source);
397
398 uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
399 const char* compileCommandLineToEmbed = "";
Yang Ni0ab50b82015-02-16 12:31:56 -0800400 const char* buildChecksum = "DummyChecksumForScriptGroup";
401 const char* buildFingerprintToEmbed = "";
402
403 RSInfo* info = RSInfo::ExtractFromSource(*source, bitcode_sha1,
404 compileCommandLineToEmbed, buildFingerprintToEmbed);
405 if (info == nullptr) {
406 return false;
407 }
408 script.setInfo(info);
409
410 // Embed the info string directly in the ELF
411 script.setEmbedInfo(true);
412 script.setOptimizationLevel(RSScript::kOptLvl3);
Yang Nia4ded132014-11-17 17:44:08 -0800413
414 llvm::SmallString<80> output_path(pOutputFilepath);
415 llvm::sys::path::replace_extension(output_path, ".o");
416
417 compileScript(script, pOutputFilepath, output_path.c_str(), pRuntimePath,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800418 bitcode_sha1, compileCommandLineToEmbed, buildChecksum,
419 true, dumpIR);
Yang Nia4ded132014-11-17 17:44:08 -0800420
421 return true;
422}
Stephen Hines331310e2012-10-26 19:27:55 -0700423
Jean-Luc Brouilletc5e607a2014-06-18 18:14:02 -0700424bool RSCompilerDriver::buildForCompatLib(RSScript &pScript, const char *pOut,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800425 const char *pBuildChecksum,
Tim Murray77c1d552015-01-22 15:15:17 -0800426 const char *pRuntimePath,
427 bool pDumpIR) {
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700428 // For compat lib, we don't check the RS info file so we don't need the source hash,
429 // compile command, and build fingerprint.
430 // TODO We may want to make them optional or embed real values.
431 uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH] = {0};
432 const char* compileCommandLineToEmbed = "";
433 const char* buildFingerprintToEmbed = "";
434
435 RSInfo* info = RSInfo::ExtractFromSource(pScript.getSource(), bitcode_sha1,
436 compileCommandLineToEmbed, buildFingerprintToEmbed);
Chris Wailes900c6c12014-08-13 15:40:00 -0700437 if (info == nullptr) {
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700438 return false;
Stephen Hines331310e2012-10-26 19:27:55 -0700439 }
440 pScript.setInfo(info);
441
Stephen Hines86a0b792012-11-06 20:04:47 -0800442 // Embed the info string directly in the ELF, since this path is for an
443 // offline (host) compilation.
444 pScript.setEmbedInfo(true);
445
Jean-Luc Brouilletf2ac3172014-06-25 18:21:36 -0700446 Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath, bitcode_sha1,
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800447 compileCommandLineToEmbed, pBuildChecksum, false, pDumpIR);
Stephen Hines47f0d5a2013-06-05 00:27:38 -0700448 if (status != Compiler::kSuccess) {
449 return false;
450 }
451
452 return true;
Stephen Hines331310e2012-10-26 19:27:55 -0700453}