14ee2ad04344446e610172a0e73949212923014dfSebastian Redl/*
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Copyright 2012, The Android Open Source Project
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Licensed under the Apache License, Version 2.0 (the "License");
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * you may not use this file except in compliance with the License.
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * You may obtain a copy of the License at
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *     http://www.apache.org/licenses/LICENSE-2.0
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl * Unless required by applicable law or agreed to in writing, software
112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * distributed under the License is distributed on an "AS IS" BASIS,
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * See the License for the specific language governing permissions and
147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl * limitations under the License.
1589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor */
160eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "bcc/Renderscript/RSCompiler.h"
18e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor
192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <llvm/IR/Module.h>
202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <llvm/PassManager.h>
212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <llvm/Transforms/IPO.h>
222a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall
2389eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis#include "bcc/Assert.h"
240b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor#include "bcc/Renderscript/RSExecutable.h"
257a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall#include "bcc/Renderscript/RSScript.h"
262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "bcc/Renderscript/RSTransforms.h"
27a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall#include "bcc/Source.h"
286ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl#include "bcc/Support/Log.h"
297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner#include "bcinfo/MetadataExtractor.h"
306a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor
317c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnerusing namespace bcc;
3283d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff
3314f79002e58556798e86168c63e48d533287eda5Douglas Gregorbool RSCompiler::addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM) {
3410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  // Add a pass to internalize the symbols that don't need to have global
353251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor  // visibility.
3614f79002e58556798e86168c63e48d533287eda5Douglas Gregor  RSScript &script = static_cast<RSScript &>(pScript);
37bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor  llvm::Module &module = script.getSource().getModule();
382bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor  bcinfo::MetadataExtractor me(&module);
39ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor  if (!me.extract()) {
400a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor    bccAssert(false && "Could not extract metadata for module!");
4117fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor    return false;
4217fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor  }
432596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar
442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // The vector contains the symbols that should not be internalized.
45fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer  std::vector<const char *> export_symbols;
4614f79002e58556798e86168c63e48d533287eda5Douglas Gregor
4703013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer  // Special RS functions should always be global symbols.
48f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor  const char **special_functions = RSExecutable::SpecialFunctionNames;
493c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner  while (*special_functions != NULL) {
50cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor    export_symbols.push_back(*special_functions);
51f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor    special_functions++;
522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
538538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Visibility of symbols appeared in rs_export_var and rs_export_func should
55ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl  // also be preserved.
565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  size_t exportVarCount = me.getExportVarCount();
575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  size_t exportFuncCount = me.getExportFuncCount();
585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  size_t exportForEachCount = me.getExportForEachSignatureCount();
596e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer  const char **exportVarNameList = me.getExportVarNameList();
60ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl  const char **exportFuncNameList = me.getExportFuncNameList();
616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer  const char **exportForEachNameList = me.getExportForEachNameList();
626e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer  size_t i;
635f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
645f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (i = 0; i < exportVarCount; ++i) {
656e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer    export_symbols.push_back(exportVarNameList[i]);
66ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl  }
67ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl
682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  for (i = 0; i < exportFuncCount; ++i) {
692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    export_symbols.push_back(exportFuncNameList[i]);
702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
7112b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner
722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Expanded foreach functions should not be internalized, too.
733397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // expanded_foreach_funcs keeps the .expand version of the kernel names
74a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl  // around until createInternalizePass() is finished making its own
7589eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis  // copy of the visible symbols.
762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  std::vector<std::string> expanded_foreach_funcs;
772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  for (i = 0; i < exportForEachCount; ++i) {
782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    expanded_foreach_funcs.push_back(
798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl        std::string(exportForEachNameList[i]) + ".expand");
802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
8189eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis
828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  for (i = 0; i < exportForEachCount; i++) {
832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      export_symbols.push_back(expanded_foreach_funcs[i].c_str());
842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  pPM.add(llvm::createInternalizePass(export_symbols));
872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  return true;
892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorbool RSCompiler::addExpandForEachPass(Script &pScript, llvm::PassManager &pPM) {
922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Script passed to RSCompiler must be a RSScript.
932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  RSScript &script = static_cast<RSScript &>(pScript);
943397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Expand ForEach on CPU path to reduce launch overhead.
962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  bool pEnableStepOpt = true;
972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  pPM.add(createRSForEachExpandPass(pEnableStepOpt));
983397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if (script.getEmbedInfo())
992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    pPM.add(createRSEmbedInfoPass());
1008538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  return true;
1022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1033397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorbool RSCompiler::beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM) {
1058538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  if (!addExpandForEachPass(pScript, pPM))
1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    return false;
1072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1083397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  if (!addInternalizeSymbolsPass(pScript, pPM))
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return false;
1108538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
1112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  return true;
1122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1133397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl