blob: 6f6e9dbb86e89e9a3b8ae3c90873f1cf5f10bf9c [file] [log] [blame]
/*
* 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