blob: b0c276780f6f65a05133c1deb3c372e6071ca7b6 [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
17#include "bcc/Assert.h"
Stephen Hinesfb81ec12015-05-18 20:04:23 -070018#include "bcc/Config/Config.h"
Stephen Hines86a0b792012-11-06 20:04:47 -080019#include "bcc/Renderscript/RSTransforms.h"
Stephen Hinesfb81ec12015-05-18 20:04:23 -070020#include "bcc/Support/Log.h"
21#include "bcinfo/MetadataExtractor.h"
22#include "rsDefines.h"
Stephen Hines86a0b792012-11-06 20:04:47 -080023
24#include <cstdlib>
Stephen Hines0116d8b2012-12-12 20:48:15 -080025#include <vector>
Stephen Hines86a0b792012-11-06 20:04:47 -080026
Stephen Hinesb730e232013-01-09 15:31:36 -080027#include <llvm/IR/DerivedTypes.h>
28#include <llvm/IR/Function.h>
29#include <llvm/IR/Instructions.h>
30#include <llvm/IR/IRBuilder.h>
31#include <llvm/IR/Module.h>
Stephen Hines86a0b792012-11-06 20:04:47 -080032#include <llvm/Pass.h>
33#include <llvm/Support/raw_ostream.h>
Stephen Hinesb730e232013-01-09 15:31:36 -080034#include <llvm/IR/Type.h>
Stephen Hines86a0b792012-11-06 20:04:47 -080035
Stephen Hines86a0b792012-11-06 20:04:47 -080036using namespace bcc;
37
38namespace {
39
Stephen Hines2d201e52014-05-08 16:51:25 -070040/* RSEmbedInfoPass - This pass operates on the entire module and embeds a
41 * string constaining relevant metadata directly as a global variable.
42 * This information does not need to be consistent across Android releases,
43 * because the standalone compiler + compatibility driver or system driver
44 * will be using the same format (i.e. bcc_compat + libRSSupport.so or
45 * bcc + libRSCpuRef are always paired together for installation).
Stephen Hines86a0b792012-11-06 20:04:47 -080046 */
47class RSEmbedInfoPass : public llvm::ModulePass {
48private:
49 static char ID;
50
51 llvm::Module *M;
52 llvm::LLVMContext *C;
53
Stephen Hines86a0b792012-11-06 20:04:47 -080054public:
Stephen Hines1253c192014-05-08 18:18:01 -070055 RSEmbedInfoPass()
Stephen Hines86a0b792012-11-06 20:04:47 -080056 : ModulePass(ID),
Chris Wailes900c6c12014-08-13 15:40:00 -070057 M(nullptr) {
Stephen Hines86a0b792012-11-06 20:04:47 -080058 }
59
Stephen Hinesc754d492015-01-08 16:00:50 -080060 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
61 AU.setPreservesAll();
62 }
63
Stephen Hines1253c192014-05-08 18:18:01 -070064 static std::string getRSInfoString(const llvm::Module *module) {
Stephen Hines86a0b792012-11-06 20:04:47 -080065 std::string str;
66 llvm::raw_string_ostream s(str);
Stephen Hines1253c192014-05-08 18:18:01 -070067 bcinfo::MetadataExtractor me(module);
68 if (!me.extract()) {
69 bccAssert(false && "Could not extract RS metadata for module!");
70 return std::string("");
71 }
72
73 size_t exportVarCount = me.getExportVarCount();
74 size_t exportFuncCount = me.getExportFuncCount();
75 size_t exportForEachCount = me.getExportForEachSignatureCount();
Matt Wala4e7a5062015-07-30 16:27:51 -070076 size_t exportReduceCount = me.getExportReduceCount();
Stephen Hines1253c192014-05-08 18:18:01 -070077 size_t objectSlotCount = me.getObjectSlotCount();
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -080078 size_t pragmaCount = me.getPragmaCount();
Stephen Hines1253c192014-05-08 18:18:01 -070079 const char **exportVarNameList = me.getExportVarNameList();
80 const char **exportFuncNameList = me.getExportFuncNameList();
81 const char **exportForEachNameList = me.getExportForEachNameList();
Matt Wala4e7a5062015-07-30 16:27:51 -070082 const char **exportReduceNameList = me.getExportReduceNameList();
Stephen Hines1253c192014-05-08 18:18:01 -070083 const uint32_t *exportForEachSignatureList =
84 me.getExportForEachSignatureList();
85 const uint32_t *objectSlotList = me.getObjectSlotList();
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -080086 const char **pragmaKeyList = me.getPragmaKeyList();
87 const char **pragmaValueList = me.getPragmaValueList();
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -080088 bool isThreadable = me.isThreadable();
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -080089 const char *buildChecksum = me.getBuildChecksum();
90
Stephen Hines1253c192014-05-08 18:18:01 -070091 size_t i;
Stephen Hines86a0b792012-11-06 20:04:47 -080092
93 // We use a simple text format here that the compatibility library can
94 // easily parse. Each section starts out with its name followed by a count.
95 // The count denotes the number of lines to parse for that particular
96 // category. Variables and Functions merely put the appropriate identifier
97 // on the line, while ForEach kernels have the encoded int signature,
98 // followed by a hyphen followed by the identifier (function to look up).
99 // Object Slots are just listed as one integer per line.
Stephen Hines1253c192014-05-08 18:18:01 -0700100 s << "exportVarCount: " << exportVarCount << "\n";
101 for (i = 0; i < exportVarCount; ++i) {
102 s << exportVarNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800103 }
104
Stephen Hines1253c192014-05-08 18:18:01 -0700105 s << "exportFuncCount: " << exportFuncCount << "\n";
106 for (i = 0; i < exportFuncCount; ++i) {
107 s << exportFuncNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800108 }
109
Stephen Hines1253c192014-05-08 18:18:01 -0700110 s << "exportForEachCount: " << exportForEachCount << "\n";
111 for (i = 0; i < exportForEachCount; ++i) {
112 s << exportForEachSignatureList[i] << " - "
113 << exportForEachNameList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800114 }
115
Matt Wala4e7a5062015-07-30 16:27:51 -0700116 s << "exportReduceCount: " << exportReduceCount << "\n";
117 for (i = 0; i < exportReduceCount; ++i) {
118 s << exportReduceNameList[i] << "\n";
119 }
120
Stephen Hines1253c192014-05-08 18:18:01 -0700121 s << "objectSlotCount: " << objectSlotCount << "\n";
122 for (i = 0; i < objectSlotCount; ++i) {
123 s << objectSlotList[i] << "\n";
Stephen Hines86a0b792012-11-06 20:04:47 -0800124 }
125
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -0800126 s << "pragmaCount: " << pragmaCount << "\n";
127 for (i = 0; i < pragmaCount; ++i) {
128 s << pragmaKeyList[i] << " - "
129 << pragmaValueList[i] << "\n";
130 }
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800131 s << "isThreadable: " << ((isThreadable) ? "yes" : "no") << "\n";
Pirama Arumuga Nainara99ef642015-01-23 14:33:42 -0800132
Stephen Hinese1c7d292015-04-15 13:20:00 -0700133 if (buildChecksum != nullptr && buildChecksum[0]) {
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800134 s << "buildChecksum: " << buildChecksum << "\n";
135 }
136
Stephen Hines86a0b792012-11-06 20:04:47 -0800137 s.flush();
Stephen Hines2d201e52014-05-08 16:51:25 -0700138 return str;
139 }
140
141 virtual bool runOnModule(llvm::Module &M) {
142 this->M = &M;
143 C = &M.getContext();
Stephen Hines86a0b792012-11-06 20:04:47 -0800144
145 // Embed this as the global variable .rs.info so that it will be
146 // accessible from the shared object later.
Stephen Hines2d201e52014-05-08 16:51:25 -0700147 llvm::Constant *Init = llvm::ConstantDataArray::getString(*C,
Stephen Hines1253c192014-05-08 18:18:01 -0700148 getRSInfoString(&M));
Stephen Hines86a0b792012-11-06 20:04:47 -0800149 llvm::GlobalVariable *InfoGV =
150 new llvm::GlobalVariable(M, Init->getType(), true,
151 llvm::GlobalValue::ExternalLinkage, Init,
Stephen Hinesfb81ec12015-05-18 20:04:23 -0700152 kRsInfo);
Stephen Hines86a0b792012-11-06 20:04:47 -0800153 (void) InfoGV;
154
155 return true;
156 }
157
158 virtual const char *getPassName() const {
159 return "Embed Renderscript Info";
160 }
161
162}; // end RSEmbedInfoPass
163
164} // end anonymous namespace
165
166char RSEmbedInfoPass::ID = 0;
167
168namespace bcc {
169
170llvm::ModulePass *
Stephen Hines1253c192014-05-08 18:18:01 -0700171createRSEmbedInfoPass() {
172 return new RSEmbedInfoPass();
Stephen Hines86a0b792012-11-06 20:04:47 -0800173}
174
175} // end namespace bcc