blob: 77208cd6e9f53fd7d4b63e9f60773fffbf59d587 [file] [log] [blame]
Stephen Hines86a0b792012-11-06 20:04:47 -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
Jean-Luc Brouilleta2dd52f2017-02-16 20:57:26 -080017#include "Assert.h"
18#include "Log.h"
19#include "RSTransforms.h"
20#include "RSUtils.h"
Stephen Hinesfb81ec12015-05-18 20:04:23 -070021#include "rsDefines.h"
Stephen Hines86a0b792012-11-06 20:04:47 -080022
Jean-Luc Brouilleta2dd52f2017-02-16 20:57:26 -080023#include "bcc/Config.h"
24#include "bcinfo/MetadataExtractor.h"
25
Luke Drummondf4c34832017-01-18 16:20:55 -080026#include <string>
Stephen Hines86a0b792012-11-06 20:04:47 -080027#include <cstdlib>
Stephen Hines0116d8b2012-12-12 20:48:15 -080028#include <vector>
Stephen Hines86a0b792012-11-06 20:04:47 -080029
Stephen Hinesb730e232013-01-09 15:31:36 -080030#include <llvm/IR/DerivedTypes.h>
31#include <llvm/IR/Function.h>
Luke Drummondf4c34832017-01-18 16:20:55 -080032#include <llvm/IR/Metadata.h>
Stephen Hinesb730e232013-01-09 15:31:36 -080033#include <llvm/IR/Instructions.h>
34#include <llvm/IR/IRBuilder.h>
35#include <llvm/IR/Module.h>
Stephen Hines86a0b792012-11-06 20:04:47 -080036#include <llvm/Pass.h>
37#include <llvm/Support/raw_ostream.h>
Stephen Hinesb730e232013-01-09 15:31:36 -080038#include <llvm/IR/Type.h>
Stephen Hines86a0b792012-11-06 20:04:47 -080039
Stephen Hines86a0b792012-11-06 20:04:47 -080040using namespace bcc;
41
42namespace {
43
Stephen Hines2d201e52014-05-08 16:51:25 -070044/* RSEmbedInfoPass - This pass operates on the entire module and embeds a
45 * string constaining relevant metadata directly as a global variable.
46 * This information does not need to be consistent across Android releases,
47 * because the standalone compiler + compatibility driver or system driver
48 * will be using the same format (i.e. bcc_compat + libRSSupport.so or
49 * bcc + libRSCpuRef are always paired together for installation).
Stephen Hines86a0b792012-11-06 20:04:47 -080050 */
51class RSEmbedInfoPass : public llvm::ModulePass {
52private:
53 static char ID;
54
55 llvm::Module *M;
56 llvm::LLVMContext *C;
57
Stephen Hines86a0b792012-11-06 20:04:47 -080058public:
Stephen Hines1253c192014-05-08 18:18:01 -070059 RSEmbedInfoPass()
Stephen Hines86a0b792012-11-06 20:04:47 -080060 : ModulePass(ID),
Chris Wailes900c6c12014-08-13 15:40:00 -070061 M(nullptr) {
Stephen Hines86a0b792012-11-06 20:04:47 -080062 }
63
Stephen Hinesc754d492015-01-08 16:00:50 -080064 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
65 AU.setPreservesAll();
66 }
67
Stephen Hines1253c192014-05-08 18:18:01 -070068 static std::string getRSInfoString(const llvm::Module *module) {
Stephen Hines86a0b792012-11-06 20:04:47 -080069 std::string str;
70 llvm::raw_string_ostream s(str);
Stephen Hines1253c192014-05-08 18:18:01 -070071 bcinfo::MetadataExtractor me(module);
72 if (!me.extract()) {
73 bccAssert(false && "Could not extract RS metadata for module!");
74 return std::string("");
75 }
76
77 size_t exportVarCount = me.getExportVarCount();
78 size_t exportFuncCount = me.getExportFuncCount();
79 size_t exportForEachCount = me.getExportForEachSignatureCount();
Matt Wala4e7a5062015-07-30 16:27:51 -070080 size_t exportReduceCount = me.getExportReduceCount();
Stephen Hines1253c192014-05-08 18:18:01 -070081 size_t objectSlotCount = me.getObjectSlotCount();
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -080082 size_t pragmaCount = me.getPragmaCount();
Stephen Hines1253c192014-05-08 18:18:01 -070083 const char **exportVarNameList = me.getExportVarNameList();
84 const char **exportFuncNameList = me.getExportFuncNameList();
85 const char **exportForEachNameList = me.getExportForEachNameList();
86 const uint32_t *exportForEachSignatureList =
87 me.getExportForEachSignatureList();
David Grossa48ea362016-06-02 14:46:55 -070088 const bcinfo::MetadataExtractor::Reduce *exportReduceList =
89 me.getExportReduceList();
Stephen Hines1253c192014-05-08 18:18:01 -070090 const uint32_t *objectSlotList = me.getObjectSlotList();
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -080091 const char **pragmaKeyList = me.getPragmaKeyList();
92 const char **pragmaValueList = me.getPragmaValueList();
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -080093 bool isThreadable = me.isThreadable();
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -080094 const char *buildChecksum = me.getBuildChecksum();
95
Stephen Hines1253c192014-05-08 18:18:01 -070096 size_t i;
Stephen Hines86a0b792012-11-06 20:04:47 -080097
David Gross79e1a052016-01-11 14:42:51 -080098 // We use a simple text format here that the compatibility library
99 // can easily parse. Each section starts out with its name
100 // followed by a count. The count denotes the number of lines to
David Grossa48ea362016-06-02 14:46:55 -0700101 // parse for that particular category. Variables and Functions
102 // merely put the appropriate identifier on the line. ForEach
103 // kernels have the encoded int signature, followed by a hyphen
104 // followed by the identifier (function to look up). General
105 // reduce kernels have the encoded int signature, followed by a
106 // hyphen followed by the accumulator data size, followed by a
107 // hyphen followed by the identifier (reduction name); and then
108 // for each possible constituent function, a hyphen followed by
109 // the identifier (function name) -- in the case where the
110 // function is omitted, "." is used in place of the identifier.
111 // Object Slots are just listed as one integer per line.
David Gross79e1a052016-01-11 14:42:51 -0800112
Stephen Hines1253c192014-05-08 18:18:01 -0700113 s << "exportVarCount: " << exportVarCount << "\n";
114 for (i = 0; i < exportVarCount; ++i) {
115 s << exportVarNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800116 }
117
Stephen Hines1253c192014-05-08 18:18:01 -0700118 s << "exportFuncCount: " << exportFuncCount << "\n";
119 for (i = 0; i < exportFuncCount; ++i) {
120 s << exportFuncNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800121 }
122
Stephen Hines1253c192014-05-08 18:18:01 -0700123 s << "exportForEachCount: " << exportForEachCount << "\n";
124 for (i = 0; i < exportForEachCount; ++i) {
125 s << exportForEachSignatureList[i] << " - "
126 << exportForEachNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800127 }
128
Matt Wala4e7a5062015-07-30 16:27:51 -0700129 s << "exportReduceCount: " << exportReduceCount << "\n";
David Grossa48ea362016-06-02 14:46:55 -0700130 auto reduceFnName = [](const char *Name) { return Name ? Name : "."; };
Matt Wala4e7a5062015-07-30 16:27:51 -0700131 for (i = 0; i < exportReduceCount; ++i) {
David Grossa48ea362016-06-02 14:46:55 -0700132 const bcinfo::MetadataExtractor::Reduce &reduce = exportReduceList[i];
133 s << reduce.mSignature << " - "
134 << reduce.mAccumulatorDataSize << " - "
135 << reduce.mReduceName << " - "
136 << reduceFnName(reduce.mInitializerName) << " - "
137 << reduceFnName(reduce.mAccumulatorName) << " - "
138 << ((reduce.mCombinerName != nullptr)
139 ? reduce.mCombinerName
140 : nameReduceCombinerFromAccumulator(reduce.mAccumulatorName)) << " - "
141 << reduceFnName(reduce.mOutConverterName) << " - "
142 << reduceFnName(reduce.mHalterName)
David Gross79e1a052016-01-11 14:42:51 -0800143 << "\n";
144 }
145
Stephen Hines1253c192014-05-08 18:18:01 -0700146 s << "objectSlotCount: " << objectSlotCount << "\n";
147 for (i = 0; i < objectSlotCount; ++i) {
148 s << objectSlotList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800149 }
150
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -0800151 s << "pragmaCount: " << pragmaCount << "\n";
152 for (i = 0; i < pragmaCount; ++i) {
153 s << pragmaKeyList[i] << " - "
154 << pragmaValueList[i] << "\n";
155 }
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800156 s << "isThreadable: " << ((isThreadable) ? "yes" : "no") << "\n";
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -0800157
Stephen Hinese1c7d292015-04-15 13:20:00 -0700158 if (buildChecksum != nullptr && buildChecksum[0]) {
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800159 s << "buildChecksum: " << buildChecksum << "\n";
160 }
161
Luke Drummondf4c34832017-01-18 16:20:55 -0800162 {
163 // As per `exportReduceCount`'s linewise fields, we use the literal `"."`
164 // to signify the empty field. This makes it easy to parse when it's
165 // missing.
166 llvm::StringRef slangVersion(".");
167 if (auto nmd = module->getNamedMetadata("slang.llvm.version")) {
168 if (auto md = nmd->getOperand(0)) {
169 if (const auto ver =
170 llvm::dyn_cast<llvm::MDString>(md->getOperand(0))) {
171 slangVersion = ver->getString();
172 }
173 }
174 }
175 s << "versionInfo: 2\n";
176 s << "bcc - " << LLVM_VERSION_STRING << "\n";
177 s << "slang - " << slangVersion << "\n";
178 if (slangVersion != LLVM_VERSION_STRING && me.hasDebugInfo()) {
179 ALOGW(
180 "The debug info in module '%s' has a different version than "
181 "expected (%s, expecting %s). The debugging experience may be "
182 "unreliable.",
183 module->getModuleIdentifier().c_str(), slangVersion.str().c_str(),
184 LLVM_VERSION_STRING);
185 }
186 }
187
Stephen Hines86a0b792012-11-06 20:04:47 -0800188 s.flush();
Stephen Hines2d201e52014-05-08 16:51:25 -0700189 return str;
190 }
191
192 virtual bool runOnModule(llvm::Module &M) {
193 this->M = &M;
194 C = &M.getContext();
Stephen Hines86a0b792012-11-06 20:04:47 -0800195
196 // Embed this as the global variable .rs.info so that it will be
197 // accessible from the shared object later.
Stephen Hines2d201e52014-05-08 16:51:25 -0700198 llvm::Constant *Init = llvm::ConstantDataArray::getString(*C,
Stephen Hines1253c192014-05-08 18:18:01 -0700199 getRSInfoString(&M));
Stephen Hines86a0b792012-11-06 20:04:47 -0800200 llvm::GlobalVariable *InfoGV =
201 new llvm::GlobalVariable(M, Init->getType(), true,
202 llvm::GlobalValue::ExternalLinkage, Init,
Stephen Hinesfb81ec12015-05-18 20:04:23 -0700203 kRsInfo);
Stephen Hines86a0b792012-11-06 20:04:47 -0800204 (void) InfoGV;
205
206 return true;
207 }
208
209 virtual const char *getPassName() const {
210 return "Embed Renderscript Info";
211 }
212
213}; // end RSEmbedInfoPass
214
215} // end anonymous namespace
216
217char RSEmbedInfoPass::ID = 0;
218
219namespace bcc {
220
221llvm::ModulePass *
Stephen Hines1253c192014-05-08 18:18:01 -0700222createRSEmbedInfoPass() {
223 return new RSEmbedInfoPass();
Stephen Hines86a0b792012-11-06 20:04:47 -0800224}
225
226} // end namespace bcc