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/Script.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 Script &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(Script& pScript, const char* pScriptName,
74                                     const char* pOutputPath,
75                                     const char* pRuntimePath,
76                                     const char* pBuildChecksum,
77                                     bool pDumpIR);
78 
79 public:
80   RSCompilerDriver();
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 
getConfig()114   const CompilerConfig * getConfig() const {
115     return mConfig;
116   }
117 
118   // Set to true if we should embed global variable information in the code.
setEmbedGlobalInfo(bool v)119   void setEmbedGlobalInfo(bool v) {
120     mEmbedGlobalInfo = v;
121   }
122 
123   // Returns true if we should embed global variable information in the code.
getEmbedGlobalInfo()124   bool getEmbedGlobalInfo() const {
125     return mEmbedGlobalInfo;
126   }
127 
128   // Set to true if we should skip constant (immutable) global variables when
129   // potentially embedding information about globals.
setEmbedGlobalInfoSkipConstant(bool v)130   void setEmbedGlobalInfoSkipConstant(bool v) {
131     mEmbedGlobalInfoSkipConstant = v;
132   }
133 
134   // Returns true if we should skip constant (immutable) global variables when
135   // potentially embedding information about globals.
getEmbedGlobalInfoSkipConstant()136   bool getEmbedGlobalInfoSkipConstant() const {
137     return mEmbedGlobalInfoSkipConstant;
138   }
139 
140   // FIXME: This method accompany with loadScript and compileScript should
141   //        all be const-methods. They're not now because the getAddress() in
142   //        SymbolResolverInterface is not a const-method.
143   // Returns true if script is successfully compiled.
144   bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
145              const char* pBitcode, size_t pBitcodeSize,
146              const char *pBuildChecksum, const char* pRuntimePath,
147              RSLinkRuntimeCallback pLinkRuntimeCallback = nullptr,
148              bool pDumpIR = false);
149 
150   bool buildScriptGroup(
151       BCCContext& Context, const char* pOutputFilepath, const char* pRuntimePath,
152       const char* pRuntimeRelaxedPath, bool dumpIR, const char* buildChecksum,
153       const std::vector<Source*>& sources,
154       const std::list<std::list<std::pair<int, int>>>& toFuse,
155       const std::list<std::string>& fused,
156       const std::list<std::list<std::pair<int, int>>>& invokes,
157       const std::list<std::string>& invokeBatchNames);
158 
159   // Returns true if script is successfully compiled.
160   bool buildForCompatLib(Script &pScript, const char *pOut,
161                          const char *pBuildChecksum, const char *pRuntimePath,
162                          bool pDumpIR);
163 };
164 
165 } // end namespace bcc
166 
167 #endif // BCC_RS_COMPILER_DRIVER_H
168