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
isPresent(std::vector<std::string> & list,const std::string & name)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:
RSIsThreadablePass()92 RSIsThreadablePass()
93 : ModulePass (ID) {
94 std::sort(nonThreadableFns.begin(), nonThreadableFns.end());
95 }
96
getAnalysisUsage(llvm::AnalysisUsage & AU) const97 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
98 AU.setPreservesAll();
99 }
100
runOnModule(llvm::Module & M)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 *
createRSIsThreadablePass()131 createRSIsThreadablePass () {
132 return new RSIsThreadablePass();
133 }
134
135 }
136