Home | History | Annotate | Download | only in Renderscript
      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 
     36 using namespace bcc;
     37 
     38 namespace {
     39 
     40 /* RSForEachExpandPass - This pass operates on functions that are able to be
     41  * called via rsForEach() or "foreach_<NAME>". We create an inner loop for the
     42  * ForEach-able function to be invoked over the appropriate data cells of the
     43  * input/output allocations (adjusting other relevant parameters as we go). We
     44  * support doing this for any ForEach-able compute kernels. The new function
     45  * name is the original function name followed by ".expand". Note that we
     46  * still generate code for the original function.
     47  */
     48 class RSEmbedInfoPass : public llvm::ModulePass {
     49 private:
     50   static char ID;
     51 
     52   llvm::Module *M;
     53   llvm::LLVMContext *C;
     54 
     55   const RSInfo *mInfo;
     56 
     57 public:
     58   RSEmbedInfoPass(const RSInfo *info)
     59       : ModulePass(ID),
     60         mInfo(info) {
     61   }
     62 
     63   virtual bool runOnModule(llvm::Module &M) {
     64     this->M = &M;
     65     C = &M.getContext();
     66 
     67     std::string str;
     68     llvm::raw_string_ostream s(str);
     69 
     70     // We use a simple text format here that the compatibility library can
     71     // easily parse. Each section starts out with its name followed by a count.
     72     // The count denotes the number of lines to parse for that particular
     73     // category. Variables and Functions merely put the appropriate identifier
     74     // on the line, while ForEach kernels have the encoded int signature,
     75     // followed by a hyphen followed by the identifier (function to look up).
     76     // Object Slots are just listed as one integer per line.
     77     const RSInfo::ExportVarNameListTy &export_vars = mInfo->getExportVarNames();
     78     s << "exportVarCount: " << (unsigned int) export_vars.size() << "\n";
     79     for (RSInfo::ExportVarNameListTy::const_iterator
     80              export_var_iter = export_vars.begin(),
     81              export_var_end = export_vars.end();
     82          export_var_iter != export_var_end; export_var_iter++) {
     83       s << *export_var_iter << "\n";
     84     }
     85 
     86     const RSInfo::ExportFuncNameListTy &export_funcs =
     87         mInfo->getExportFuncNames();
     88     s << "exportFuncCount: " << (unsigned int) export_funcs.size() << "\n";
     89     for (RSInfo::ExportFuncNameListTy::const_iterator
     90              export_func_iter = export_funcs.begin(),
     91              export_func_end = export_funcs.end();
     92          export_func_iter != export_func_end; export_func_iter++) {
     93       s << *export_func_iter << "\n";
     94     }
     95 
     96     const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
     97         mInfo->getExportForeachFuncs();
     98     s << "exportForEachCount: "
     99       << (unsigned int) export_foreach_funcs.size() << "\n";
    100     for (RSInfo::ExportForeachFuncListTy::const_iterator
    101              foreach_func_iter = export_foreach_funcs.begin(),
    102              foreach_func_end = export_foreach_funcs.end();
    103          foreach_func_iter != foreach_func_end; foreach_func_iter++) {
    104       std::string name(foreach_func_iter->first);
    105       s << foreach_func_iter->second << " - "
    106         << foreach_func_iter->first << "\n";
    107     }
    108 
    109     std::vector<unsigned int> object_slot_numbers;
    110     unsigned int i = 0;
    111     const RSInfo::ObjectSlotListTy &object_slots = mInfo->getObjectSlots();
    112     for (RSInfo::ObjectSlotListTy::const_iterator
    113              slots_iter = object_slots.begin(),
    114              slots_end = object_slots.end();
    115          slots_iter != slots_end; slots_iter++) {
    116       if (*slots_iter) {
    117         object_slot_numbers.push_back(i);
    118       }
    119       i++;
    120     }
    121     s << "objectSlotCount: " << (unsigned int) object_slot_numbers.size()
    122       << "\n";
    123     for (i = 0; i < object_slot_numbers.size(); i++) {
    124       s << object_slot_numbers[i] << "\n";
    125     }
    126 
    127     s.flush();
    128 
    129     // Embed this as the global variable .rs.info so that it will be
    130     // accessible from the shared object later.
    131     llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, str);
    132     llvm::GlobalVariable *InfoGV =
    133         new llvm::GlobalVariable(M, Init->getType(), true,
    134                                  llvm::GlobalValue::ExternalLinkage, Init,
    135                                  ".rs.info");
    136     (void) InfoGV;
    137 
    138     return true;
    139   }
    140 
    141   virtual const char *getPassName() const {
    142     return "Embed Renderscript Info";
    143   }
    144 
    145 };  // end RSEmbedInfoPass
    146 
    147 }  // end anonymous namespace
    148 
    149 char RSEmbedInfoPass::ID = 0;
    150 
    151 namespace bcc {
    152 
    153 llvm::ModulePass *
    154 createRSEmbedInfoPass(const RSInfo *info) {
    155   return new RSEmbedInfoPass(info);
    156 }
    157 
    158 }  // end namespace bcc
    159