1 /* 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" 18 #include "bcc/Config/Config.h" 19 #include "bcc/Renderscript/RSTransforms.h" 20 #include "bcc/Support/Log.h" 21 #include "bcinfo/MetadataExtractor.h" 22 #include "rsDefines.h" 23 24 #include <cstdlib> 25 #include <vector> 26 27 #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> 32 #include <llvm/Pass.h> 33 #include <llvm/Support/raw_ostream.h> 34 #include <llvm/IR/Type.h> 35 36 using namespace bcc; 37 38 namespace { 39 40 /* 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). 46 */ 47 class RSEmbedInfoPass : public llvm::ModulePass { 48 private: 49 static char ID; 50 51 llvm::Module *M; 52 llvm::LLVMContext *C; 53 54 public: 55 RSEmbedInfoPass() 56 : ModulePass(ID), 57 M(nullptr) { 58 } 59 60 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { 61 AU.setPreservesAll(); 62 } 63 64 static std::string getRSInfoString(const llvm::Module *module) { 65 std::string str; 66 llvm::raw_string_ostream s(str); 67 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(); 76 size_t objectSlotCount = me.getObjectSlotCount(); 77 size_t pragmaCount = me.getPragmaCount(); 78 const char **exportVarNameList = me.getExportVarNameList(); 79 const char **exportFuncNameList = me.getExportFuncNameList(); 80 const char **exportForEachNameList = me.getExportForEachNameList(); 81 const uint32_t *exportForEachSignatureList = 82 me.getExportForEachSignatureList(); 83 const uint32_t *objectSlotList = me.getObjectSlotList(); 84 const char **pragmaKeyList = me.getPragmaKeyList(); 85 const char **pragmaValueList = me.getPragmaValueList(); 86 bool isThreadable = me.isThreadable(); 87 const char *buildChecksum = me.getBuildChecksum(); 88 89 size_t i; 90 91 // We use a simple text format here that the compatibility library can 92 // easily parse. Each section starts out with its name followed by a count. 93 // The count denotes the number of lines to parse for that particular 94 // category. Variables and Functions merely put the appropriate identifier 95 // on the line, while ForEach kernels have the encoded int signature, 96 // followed by a hyphen followed by the identifier (function to look up). 97 // Object Slots are just listed as one integer per line. 98 s << "exportVarCount: " << exportVarCount << "\n"; 99 for (i = 0; i < exportVarCount; ++i) { 100 s << exportVarNameList[i] << "\n"; 101 } 102 103 s << "exportFuncCount: " << exportFuncCount << "\n"; 104 for (i = 0; i < exportFuncCount; ++i) { 105 s << exportFuncNameList[i] << "\n"; 106 } 107 108 s << "exportForEachCount: " << exportForEachCount << "\n"; 109 for (i = 0; i < exportForEachCount; ++i) { 110 s << exportForEachSignatureList[i] << " - " 111 << exportForEachNameList[i] << "\n"; 112 } 113 114 s << "objectSlotCount: " << objectSlotCount << "\n"; 115 for (i = 0; i < objectSlotCount; ++i) { 116 s << objectSlotList[i] << "\n"; 117 } 118 119 s << "pragmaCount: " << pragmaCount << "\n"; 120 for (i = 0; i < pragmaCount; ++i) { 121 s << pragmaKeyList[i] << " - " 122 << pragmaValueList[i] << "\n"; 123 } 124 s << "isThreadable: " << ((isThreadable) ? "yes" : "no") << "\n"; 125 126 if (buildChecksum != nullptr && buildChecksum[0]) { 127 s << "buildChecksum: " << buildChecksum << "\n"; 128 } 129 130 s.flush(); 131 return str; 132 } 133 134 virtual bool runOnModule(llvm::Module &M) { 135 this->M = &M; 136 C = &M.getContext(); 137 138 // Embed this as the global variable .rs.info so that it will be 139 // accessible from the shared object later. 140 llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, 141 getRSInfoString(&M)); 142 llvm::GlobalVariable *InfoGV = 143 new llvm::GlobalVariable(M, Init->getType(), true, 144 llvm::GlobalValue::ExternalLinkage, Init, 145 kRsInfo); 146 (void) InfoGV; 147 148 return true; 149 } 150 151 virtual const char *getPassName() const { 152 return "Embed Renderscript Info"; 153 } 154 155 }; // end RSEmbedInfoPass 156 157 } // end anonymous namespace 158 159 char RSEmbedInfoPass::ID = 0; 160 161 namespace bcc { 162 163 llvm::ModulePass * 164 createRSEmbedInfoPass() { 165 return new RSEmbedInfoPass(); 166 } 167 168 } // end namespace bcc 169