/* * Copyright 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bcc/Assert.h" #include "bcc/Renderscript/RSTransforms.h" #include <cstdlib> #include <vector> #include <llvm/IR/DerivedTypes.h> #include <llvm/IR/Function.h> #include <llvm/IR/Instructions.h> #include <llvm/IR/IRBuilder.h> #include <llvm/IR/Module.h> #include <llvm/Pass.h> #include <llvm/Support/raw_ostream.h> #include <llvm/IR/Type.h> #include "bcc/Config/Config.h" #include "bcc/Renderscript/RSInfo.h" #include "bcc/Support/Log.h" using namespace bcc; namespace { /* RSForEachExpandPass - This pass operates on functions that are able to be * called via rsForEach() or "foreach_<NAME>". We create an inner loop for the * ForEach-able function to be invoked over the appropriate data cells of the * input/output allocations (adjusting other relevant parameters as we go). We * support doing this for any ForEach-able compute kernels. The new function * name is the original function name followed by ".expand". Note that we * still generate code for the original function. */ class RSEmbedInfoPass : public llvm::ModulePass { private: static char ID; llvm::Module *M; llvm::LLVMContext *C; const RSInfo *mInfo; public: RSEmbedInfoPass(const RSInfo *info) : ModulePass(ID), mInfo(info) { } virtual bool runOnModule(llvm::Module &M) { this->M = &M; C = &M.getContext(); std::string str; llvm::raw_string_ostream s(str); // We use a simple text format here that the compatibility library can // easily parse. Each section starts out with its name followed by a count. // The count denotes the number of lines to parse for that particular // category. Variables and Functions merely put the appropriate identifier // on the line, while ForEach kernels have the encoded int signature, // followed by a hyphen followed by the identifier (function to look up). // Object Slots are just listed as one integer per line. const RSInfo::ExportVarNameListTy &export_vars = mInfo->getExportVarNames(); s << "exportVarCount: " << (unsigned int) export_vars.size() << "\n"; for (RSInfo::ExportVarNameListTy::const_iterator export_var_iter = export_vars.begin(), export_var_end = export_vars.end(); export_var_iter != export_var_end; export_var_iter++) { s << *export_var_iter << "\n"; } const RSInfo::ExportFuncNameListTy &export_funcs = mInfo->getExportFuncNames(); s << "exportFuncCount: " << (unsigned int) export_funcs.size() << "\n"; for (RSInfo::ExportFuncNameListTy::const_iterator export_func_iter = export_funcs.begin(), export_func_end = export_funcs.end(); export_func_iter != export_func_end; export_func_iter++) { s << *export_func_iter << "\n"; } const RSInfo::ExportForeachFuncListTy &export_foreach_funcs = mInfo->getExportForeachFuncs(); s << "exportForEachCount: " << (unsigned int) export_foreach_funcs.size() << "\n"; for (RSInfo::ExportForeachFuncListTy::const_iterator foreach_func_iter = export_foreach_funcs.begin(), foreach_func_end = export_foreach_funcs.end(); foreach_func_iter != foreach_func_end; foreach_func_iter++) { std::string name(foreach_func_iter->first); s << foreach_func_iter->second << " - " << foreach_func_iter->first << "\n"; } std::vector<unsigned int> object_slot_numbers; unsigned int i = 0; const RSInfo::ObjectSlotListTy &object_slots = mInfo->getObjectSlots(); for (RSInfo::ObjectSlotListTy::const_iterator slots_iter = object_slots.begin(), slots_end = object_slots.end(); slots_iter != slots_end; slots_iter++) { if (*slots_iter) { object_slot_numbers.push_back(i); } i++; } s << "objectSlotCount: " << (unsigned int) object_slot_numbers.size() << "\n"; for (i = 0; i < object_slot_numbers.size(); i++) { s << object_slot_numbers[i] << "\n"; } s.flush(); // Embed this as the global variable .rs.info so that it will be // accessible from the shared object later. llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, str); llvm::GlobalVariable *InfoGV = new llvm::GlobalVariable(M, Init->getType(), true, llvm::GlobalValue::ExternalLinkage, Init, ".rs.info"); (void) InfoGV; return true; } virtual const char *getPassName() const { return "Embed Renderscript Info"; } }; // end RSEmbedInfoPass } // end anonymous namespace char RSEmbedInfoPass::ID = 0; namespace bcc { llvm::ModulePass * createRSEmbedInfoPass(const RSInfo *info) { return new RSEmbedInfoPass(info); } } // end namespace bcc