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/Renderscript/RSCompiler.h" 18 19 #include <llvm/IR/Module.h> 20 #include <llvm/PassManager.h> 21 #include <llvm/Transforms/IPO.h> 22 23 #include "bcc/Assert.h" 24 #include "bcc/Renderscript/RSExecutable.h" 25 #include "bcc/Renderscript/RSScript.h" 26 #include "bcc/Renderscript/RSTransforms.h" 27 #include "bcc/Source.h" 28 #include "bcc/Support/Log.h" 29 #include "bcinfo/MetadataExtractor.h" 30 31 using namespace bcc; 32 33 bool RSCompiler::addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM) { 34 // Add a pass to internalize the symbols that don't need to have global 35 // visibility. 36 RSScript &script = static_cast<RSScript &>(pScript); 37 llvm::Module &module = script.getSource().getModule(); 38 bcinfo::MetadataExtractor me(&module); 39 if (!me.extract()) { 40 bccAssert(false && "Could not extract metadata for module!"); 41 return false; 42 } 43 44 // The vector contains the symbols that should not be internalized. 45 std::vector<const char *> export_symbols; 46 47 // Special RS functions should always be global symbols. 48 const char **special_functions = RSExecutable::SpecialFunctionNames; 49 while (*special_functions != NULL) { 50 export_symbols.push_back(*special_functions); 51 special_functions++; 52 } 53 54 // Visibility of symbols appeared in rs_export_var and rs_export_func should 55 // also be preserved. 56 size_t exportVarCount = me.getExportVarCount(); 57 size_t exportFuncCount = me.getExportFuncCount(); 58 size_t exportForEachCount = me.getExportForEachSignatureCount(); 59 const char **exportVarNameList = me.getExportVarNameList(); 60 const char **exportFuncNameList = me.getExportFuncNameList(); 61 const char **exportForEachNameList = me.getExportForEachNameList(); 62 size_t i; 63 64 for (i = 0; i < exportVarCount; ++i) { 65 export_symbols.push_back(exportVarNameList[i]); 66 } 67 68 for (i = 0; i < exportFuncCount; ++i) { 69 export_symbols.push_back(exportFuncNameList[i]); 70 } 71 72 // Expanded foreach functions should not be internalized, too. 73 // expanded_foreach_funcs keeps the .expand version of the kernel names 74 // around until createInternalizePass() is finished making its own 75 // copy of the visible symbols. 76 std::vector<std::string> expanded_foreach_funcs; 77 for (i = 0; i < exportForEachCount; ++i) { 78 expanded_foreach_funcs.push_back( 79 std::string(exportForEachNameList[i]) + ".expand"); 80 } 81 82 for (i = 0; i < exportForEachCount; i++) { 83 export_symbols.push_back(expanded_foreach_funcs[i].c_str()); 84 } 85 86 pPM.add(llvm::createInternalizePass(export_symbols)); 87 88 return true; 89 } 90 91 bool RSCompiler::addExpandForEachPass(Script &pScript, llvm::PassManager &pPM) { 92 // Script passed to RSCompiler must be a RSScript. 93 RSScript &script = static_cast<RSScript &>(pScript); 94 95 // Expand ForEach on CPU path to reduce launch overhead. 96 bool pEnableStepOpt = true; 97 pPM.add(createRSForEachExpandPass(pEnableStepOpt)); 98 if (script.getEmbedInfo()) 99 pPM.add(createRSEmbedInfoPass()); 100 101 return true; 102 } 103 104 bool RSCompiler::beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM) { 105 if (!addExpandForEachPass(pScript, pPM)) 106 return false; 107 108 if (!addInternalizeSymbolsPass(pScript, pPM)) 109 return false; 110 111 return true; 112 } 113