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 #ifndef BCC_RS_COMPILER_DRIVER_H
18 #define BCC_RS_COMPILER_DRIVER_H
19 
20 #include "bcc/Compiler.h"
21 #include "bcc/Renderscript/RSScript.h"
22 
23 #include "bcinfo/MetadataExtractor.h"
24 
25 #include <list>
26 #include <string>
27 #include <vector>
28 
29 namespace bcc {
30 
31 class BCCContext;
32 class CompilerConfig;
33 class RSCompilerDriver;
34 class Source;
35 
36 // Type signature for dynamically loaded initialization of an RSCompilerDriver.
37 typedef void (*RSCompilerDriverInit_t) (bcc::RSCompilerDriver *);
38 // Name of the function that we attempt to dynamically load/execute.
39 #define RS_COMPILER_DRIVER_INIT_FN rsCompilerDriverInit
40 
41 class RSCompilerDriver {
42 private:
43   CompilerConfig *mConfig;
44   Compiler mCompiler;
45 
46   // Are we compiling under an RS debug context with additional checks?
47   bool mDebugContext;
48 
49   // Callback before linking with the runtime library.
50   RSLinkRuntimeCallback mLinkRuntimeCallback;
51 
52   // Do we merge global variables on ARM using LLVM's optimization pass?
53   // Disabling LLVM's global merge pass allows static globals to be correctly
54   // emitted to ELF. This can result in decreased performance due to increased
55   // register pressure, but it does make the resulting code easier to debug
56   // and work with.
57   bool mEnableGlobalMerge;
58 
59   // Specifies whether we should embed global variable information in the
60   // code via special RS variables that can be examined later by the driver.
61   bool mEmbedGlobalInfo;
62 
63   // Specifies whether we should skip constant (immutable) global variables
64   // when potentially embedding information about globals.
65   bool mEmbedGlobalInfoSkipConstant;
66 
67   // Setup the compiler config for the given script. Return true if mConfig has
68   // been changed and false if it remains unchanged.
69   bool setupConfig(const RSScript &pScript);
70 
71   // Compiles the provided bitcode, placing the binary at pOutputPath.
72   // - If pDumpIR is true, a ".ll" file will also be created.
73   Compiler::ErrorCode compileScript(RSScript& pScript, const char* pScriptName,
74                                     const char* pOutputPath,
75                                     const char* pRuntimePath,
76                                     const char* pBuildChecksum,
77                                     bool pDumpIR);
78 
79 public:
80   RSCompilerDriver(bool pUseCompilerRT = true);
81   ~RSCompilerDriver();
82 
getCompiler()83   Compiler *getCompiler() {
84     return &mCompiler;
85   }
86 
setConfig(CompilerConfig * config)87   void setConfig(CompilerConfig *config) {
88     mConfig = config;
89   }
90 
setDebugContext(bool v)91   void setDebugContext(bool v) {
92     mDebugContext = v;
93   }
94 
setLinkRuntimeCallback(RSLinkRuntimeCallback c)95   void setLinkRuntimeCallback(RSLinkRuntimeCallback c) {
96     mLinkRuntimeCallback = c;
97   }
98 
getLinkRuntimeCallback()99   RSLinkRuntimeCallback getLinkRuntimeCallback() const {
100     return mLinkRuntimeCallback;
101   }
102 
103   // This function enables/disables merging of global static variables.
104   // Note that it only takes effect on ARM architectures (other architectures
105   // do not offer this option).
setEnableGlobalMerge(bool v)106   void setEnableGlobalMerge(bool v) {
107     mEnableGlobalMerge = v;
108   }
109 
getEnableGlobalMerge()110   bool getEnableGlobalMerge() const {
111     return mEnableGlobalMerge;
112   }
113 
114   // Set to true if we should embed global variable information in the code.
setEmbedGlobalInfo(bool v)115   void setEmbedGlobalInfo(bool v) {
116     mEmbedGlobalInfo = v;
117   }
118 
119   // Returns true if we should embed global variable information in the code.
getEmbedGlobalInfo()120   bool getEmbedGlobalInfo() const {
121     return mEmbedGlobalInfo;
122   }
123 
124   // Set to true if we should skip constant (immutable) global variables when
125   // potentially embedding information about globals.
setEmbedGlobalInfoSkipConstant(bool v)126   void setEmbedGlobalInfoSkipConstant(bool v) {
127     mEmbedGlobalInfoSkipConstant = v;
128   }
129 
130   // Returns true if we should skip constant (immutable) global variables when
131   // potentially embedding information about globals.
getEmbedGlobalInfoSkipConstant()132   bool getEmbedGlobalInfoSkipConstant() const {
133     return mEmbedGlobalInfoSkipConstant;
134   }
135 
136   // FIXME: This method accompany with loadScript and compileScript should
137   //        all be const-methods. They're not now because the getAddress() in
138   //        SymbolResolverInterface is not a const-method.
139   // Returns true if script is successfully compiled.
140   bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
141              const char* pBitcode, size_t pBitcodeSize,
142              const char *pBuildChecksum, const char* pRuntimePath,
143              RSLinkRuntimeCallback pLinkRuntimeCallback = nullptr,
144              bool pDumpIR = false);
145 
146   bool buildScriptGroup(
147       BCCContext& Context, const char* pOutputFilepath, const char* pRuntimePath,
148       const char* pRuntimeRelaxedPath, bool dumpIR, const char* buildChecksum,
149       const std::vector<Source*>& sources,
150       const std::list<std::list<std::pair<int, int>>>& toFuse,
151       const std::list<std::string>& fused,
152       const std::list<std::list<std::pair<int, int>>>& invokes,
153       const std::list<std::string>& invokeBatchNames);
154 
155   // Returns true if script is successfully compiled.
156   bool buildForCompatLib(RSScript &pScript, const char *pOut,
157                          const char *pBuildChecksum, const char *pRuntimePath,
158                          bool pDumpIR);
159 };
160 
161 } // end namespace bcc
162 
163 #endif // BCC_RS_COMPILER_DRIVER_H
164