RSEmbedInfo.cpp revision 2d201e547f1d32140ff8ead1818c169f441cf5fb
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/Renderscript/RSTransforms.h" 19 20#include <cstdlib> 21#include <vector> 22 23#include <llvm/IR/DerivedTypes.h> 24#include <llvm/IR/Function.h> 25#include <llvm/IR/Instructions.h> 26#include <llvm/IR/IRBuilder.h> 27#include <llvm/IR/Module.h> 28#include <llvm/Pass.h> 29#include <llvm/Support/raw_ostream.h> 30#include <llvm/IR/Type.h> 31 32#include "bcc/Config/Config.h" 33#include "bcc/Renderscript/RSInfo.h" 34#include "bcc/Support/Log.h" 35 36using namespace bcc; 37 38namespace { 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 */ 47class RSEmbedInfoPass : public llvm::ModulePass { 48private: 49 static char ID; 50 51 llvm::Module *M; 52 llvm::LLVMContext *C; 53 54 const RSInfo *mInfo; 55 56public: 57 RSEmbedInfoPass(const RSInfo *info) 58 : ModulePass(ID), 59 mInfo(info) { 60 } 61 62 static std::string getRSInfoString(const RSInfo *info) { 63 std::string str; 64 llvm::raw_string_ostream s(str); 65 66 // We use a simple text format here that the compatibility library can 67 // easily parse. Each section starts out with its name followed by a count. 68 // The count denotes the number of lines to parse for that particular 69 // category. Variables and Functions merely put the appropriate identifier 70 // on the line, while ForEach kernels have the encoded int signature, 71 // followed by a hyphen followed by the identifier (function to look up). 72 // Object Slots are just listed as one integer per line. 73 const RSInfo::ExportVarNameListTy &export_vars = info->getExportVarNames(); 74 s << "exportVarCount: " << (unsigned int) export_vars.size() << "\n"; 75 for (RSInfo::ExportVarNameListTy::const_iterator 76 export_var_iter = export_vars.begin(), 77 export_var_end = export_vars.end(); 78 export_var_iter != export_var_end; export_var_iter++) { 79 s << *export_var_iter << "\n"; 80 } 81 82 const RSInfo::ExportFuncNameListTy &export_funcs = 83 info->getExportFuncNames(); 84 s << "exportFuncCount: " << (unsigned int) export_funcs.size() << "\n"; 85 for (RSInfo::ExportFuncNameListTy::const_iterator 86 export_func_iter = export_funcs.begin(), 87 export_func_end = export_funcs.end(); 88 export_func_iter != export_func_end; export_func_iter++) { 89 s << *export_func_iter << "\n"; 90 } 91 92 const RSInfo::ExportForeachFuncListTy &export_foreach_funcs = 93 info->getExportForeachFuncs(); 94 s << "exportForEachCount: " 95 << (unsigned int) export_foreach_funcs.size() << "\n"; 96 for (RSInfo::ExportForeachFuncListTy::const_iterator 97 foreach_func_iter = export_foreach_funcs.begin(), 98 foreach_func_end = export_foreach_funcs.end(); 99 foreach_func_iter != foreach_func_end; foreach_func_iter++) { 100 std::string name(foreach_func_iter->first); 101 s << foreach_func_iter->second << " - " 102 << foreach_func_iter->first << "\n"; 103 } 104 105 std::vector<unsigned int> object_slot_numbers; 106 unsigned int i = 0; 107 const RSInfo::ObjectSlotListTy &object_slots = info->getObjectSlots(); 108 for (RSInfo::ObjectSlotListTy::const_iterator 109 slots_iter = object_slots.begin(), 110 slots_end = object_slots.end(); 111 slots_iter != slots_end; slots_iter++) { 112 if (*slots_iter) { 113 object_slot_numbers.push_back(i); 114 } 115 i++; 116 } 117 s << "objectSlotCount: " << (unsigned int) object_slot_numbers.size() 118 << "\n"; 119 for (i = 0; i < object_slot_numbers.size(); i++) { 120 s << object_slot_numbers[i] << "\n"; 121 } 122 123 s.flush(); 124 return str; 125 } 126 127 virtual bool runOnModule(llvm::Module &M) { 128 this->M = &M; 129 C = &M.getContext(); 130 131 // Embed this as the global variable .rs.info so that it will be 132 // accessible from the shared object later. 133 llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, 134 getRSInfoString(mInfo)); 135 llvm::GlobalVariable *InfoGV = 136 new llvm::GlobalVariable(M, Init->getType(), true, 137 llvm::GlobalValue::ExternalLinkage, Init, 138 ".rs.info"); 139 (void) InfoGV; 140 141 return true; 142 } 143 144 virtual const char *getPassName() const { 145 return "Embed Renderscript Info"; 146 } 147 148}; // end RSEmbedInfoPass 149 150} // end anonymous namespace 151 152char RSEmbedInfoPass::ID = 0; 153 154namespace bcc { 155 156llvm::ModulePass * 157createRSEmbedInfoPass(const RSInfo *info) { 158 return new RSEmbedInfoPass(info); 159} 160 161} // end namespace bcc 162