186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines/* 286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Copyright 2012, The Android Open Source Project 386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * 486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * you may not use this file except in compliance with the License. 686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * You may obtain a copy of the License at 786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * 886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * http://www.apache.org/licenses/LICENSE-2.0 986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * 1086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Unless required by applicable law or agreed to in writing, software 1186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 1286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * See the License for the specific language governing permissions and 1486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * limitations under the License. 1586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines */ 1686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 1786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Assert.h" 1886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Renderscript/RSTransforms.h" 1986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 2086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <cstdlib> 210116d8b4247829adfb64b9cb7992eb783a54abd5Stephen Hines#include <vector> 2286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 23b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/DerivedTypes.h> 24b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Function.h> 25b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Instructions.h> 26b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/IRBuilder.h> 27b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h> 2886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <llvm/Pass.h> 2986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <llvm/Support/raw_ostream.h> 30b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Type.h> 3186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 3286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Config/Config.h" 3386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Support/Log.h" 341253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines#include "bcinfo/MetadataExtractor.h" 3586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 3686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesusing namespace bcc; 3786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 3886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesnamespace { 3986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 402d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines/* RSEmbedInfoPass - This pass operates on the entire module and embeds a 412d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * string constaining relevant metadata directly as a global variable. 422d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * This information does not need to be consistent across Android releases, 432d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * because the standalone compiler + compatibility driver or system driver 442d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * will be using the same format (i.e. bcc_compat + libRSSupport.so or 452d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * bcc + libRSCpuRef are always paired together for installation). 4686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines */ 4786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesclass RSEmbedInfoPass : public llvm::ModulePass { 4886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesprivate: 4986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines static char ID; 5086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 5186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines llvm::Module *M; 5286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines llvm::LLVMContext *C; 5386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 5486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinespublic: 551253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines RSEmbedInfoPass() 5686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines : ModulePass(ID), 571253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines M(NULL) { 5886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 5986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 601253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines static std::string getRSInfoString(const llvm::Module *module) { 6186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines std::string str; 6286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines llvm::raw_string_ostream s(str); 631253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines bcinfo::MetadataExtractor me(module); 641253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines if (!me.extract()) { 651253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines bccAssert(false && "Could not extract RS metadata for module!"); 661253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines return std::string(""); 671253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines } 681253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines 691253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines size_t exportVarCount = me.getExportVarCount(); 701253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines size_t exportFuncCount = me.getExportFuncCount(); 711253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines size_t exportForEachCount = me.getExportForEachSignatureCount(); 721253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines size_t objectSlotCount = me.getObjectSlotCount(); 731253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines const char **exportVarNameList = me.getExportVarNameList(); 741253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines const char **exportFuncNameList = me.getExportFuncNameList(); 751253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines const char **exportForEachNameList = me.getExportForEachNameList(); 761253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines const uint32_t *exportForEachSignatureList = 771253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines me.getExportForEachSignatureList(); 781253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines const uint32_t *objectSlotList = me.getObjectSlotList(); 791253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines size_t i; 8086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 8186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // We use a simple text format here that the compatibility library can 8286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // easily parse. Each section starts out with its name followed by a count. 8386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // The count denotes the number of lines to parse for that particular 8486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // category. Variables and Functions merely put the appropriate identifier 8586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // on the line, while ForEach kernels have the encoded int signature, 8686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // followed by a hyphen followed by the identifier (function to look up). 8786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // Object Slots are just listed as one integer per line. 881253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << "exportVarCount: " << exportVarCount << "\n"; 891253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines for (i = 0; i < exportVarCount; ++i) { 901253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << exportVarNameList[i] << "\n"; 9186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 9286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 931253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << "exportFuncCount: " << exportFuncCount << "\n"; 941253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines for (i = 0; i < exportFuncCount; ++i) { 951253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << exportFuncNameList[i] << "\n"; 9686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 9786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 981253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << "exportForEachCount: " << exportForEachCount << "\n"; 991253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines for (i = 0; i < exportForEachCount; ++i) { 1001253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << exportForEachSignatureList[i] << " - " 1011253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines << exportForEachNameList[i] << "\n"; 10286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 10386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 1041253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << "objectSlotCount: " << objectSlotCount << "\n"; 1051253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines for (i = 0; i < objectSlotCount; ++i) { 1061253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines s << objectSlotList[i] << "\n"; 10786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 10886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 10986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines s.flush(); 1102d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines return str; 1112d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines } 1122d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines 1132d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines virtual bool runOnModule(llvm::Module &M) { 1142d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines this->M = &M; 1152d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines C = &M.getContext(); 11686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 11786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // Embed this as the global variable .rs.info so that it will be 11886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines // accessible from the shared object later. 1192d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, 1201253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines getRSInfoString(&M)); 12186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines llvm::GlobalVariable *InfoGV = 12286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines new llvm::GlobalVariable(M, Init->getType(), true, 12386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines llvm::GlobalValue::ExternalLinkage, Init, 12486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines ".rs.info"); 12586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines (void) InfoGV; 12686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 12786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines return true; 12886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 12986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 13086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines virtual const char *getPassName() const { 13186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines return "Embed Renderscript Info"; 13286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines } 13386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 13486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines}; // end RSEmbedInfoPass 13586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 13686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines} // end anonymous namespace 13786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 13886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hineschar RSEmbedInfoPass::ID = 0; 13986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 14086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesnamespace bcc { 14186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 14286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesllvm::ModulePass * 1431253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen HinescreateRSEmbedInfoPass() { 1441253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines return new RSEmbedInfoPass(); 14586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines} 14686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines 14786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines} // end namespace bcc 148