1 /* 2 * Copyright 2015, 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 "Log.h" 18 #include "RSTransforms.h" 19 20 #include <cstdlib> 21 22 #include <llvm/IR/Instructions.h> 23 #include <llvm/IR/Metadata.h> 24 #include <llvm/IR/Module.h> 25 #include <llvm/IR/Function.h> 26 #include <llvm/Pass.h> 27 28 namespace { // anonymous namespace 29 30 // Create a Module pass that screens all the global functions in the module and 31 // check if any non-threadable function is callable. If so, we mark the 32 // Module as non-threadable by adding a metadata flag '#rs_is_threadable' 33 34 class RSIsThreadablePass : public llvm::ModulePass { 35 private: 36 static char ID; 37 38 std::vector<std::string> nonThreadableFns = { 39 "_Z22rsgBindProgramFragment19rs_program_fragment", 40 "_Z19rsgBindProgramStore16rs_program_store", 41 "_Z20rsgBindProgramVertex17rs_program_vertex", 42 "_Z20rsgBindProgramRaster17rs_program_raster", 43 "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler", 44 "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation", 45 "_Z15rsgBindConstant19rs_program_fragmentj13rs_allocation", 46 "_Z15rsgBindConstant17rs_program_vertexj13rs_allocation", 47 "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4", 48 "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", 49 "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4", 50 "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4", 51 "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff", 52 "_Z11rsgGetWidthv", 53 "_Z12rsgGetHeightv", 54 "_Z11rsgDrawRectfffff", 55 "_Z11rsgDrawQuadffffffffffff", 56 "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff", 57 "_Z24rsgDrawSpriteScreenspacefffff", 58 "_Z11rsgDrawMesh7rs_mesh", 59 "_Z11rsgDrawMesh7rs_meshj", 60 "_Z11rsgDrawMesh7rs_meshjjj", 61 "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", 62 "_Z11rsgDrawPath7rs_path", 63 "_Z13rsgClearColorffff", 64 "_Z13rsgClearDepthf", 65 "_Z11rsgDrawTextPKcii", 66 "_Z11rsgDrawText13rs_allocationii", 67 "_Z14rsgMeasureTextPKcPiS1_S1_S1_", 68 "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_", 69 "_Z11rsgBindFont7rs_font", 70 "_Z12rsgFontColorffff", 71 "_Z18rsgBindColorTarget13rs_allocationj", 72 "_Z18rsgBindDepthTarget13rs_allocation", 73 "_Z19rsgClearColorTargetj", 74 "_Z19rsgClearDepthTargetv", 75 "_Z24rsgClearAllRenderTargetsv", 76 "_Z7rsGetDtv", 77 "_Z5colorffff", 78 "_Z9rsgFinishv", 79 }; 80 81 bool isPresent(std::vector<std::string> &list, const std::string &name) { 82 auto lower = std::lower_bound(list.begin(), 83 list.end(), 84 name); 85 86 if (lower != list.end() && name.compare(*lower) == 0) 87 return true; 88 return false; 89 } 90 91 public: 92 RSIsThreadablePass() 93 : ModulePass (ID) { 94 std::sort(nonThreadableFns.begin(), nonThreadableFns.end()); 95 } 96 97 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { 98 AU.setPreservesAll(); 99 } 100 101 bool runOnModule(llvm::Module &M) override { 102 bool threadable = true; 103 104 auto &FunctionList(M.getFunctionList()); 105 for (auto &F: FunctionList) { 106 if (isPresent(nonThreadableFns, F.getName().str())) { 107 threadable = false; 108 break; 109 } 110 } 111 112 llvm::LLVMContext &context = M.getContext(); 113 llvm::MDString *val = 114 llvm::MDString::get(context, (threadable) ? "yes" : "no"); 115 llvm::NamedMDNode *node = 116 M.getOrInsertNamedMetadata("#rs_is_threadable"); 117 node->addOperand(llvm::MDNode::get(context, val)); 118 119 return false; 120 } 121 122 }; 123 124 } 125 126 char RSIsThreadablePass::ID = 0; 127 128 namespace bcc { 129 130 llvm::ModulePass * 131 createRSIsThreadablePass () { 132 return new RSIsThreadablePass(); 133 } 134 135 } 136