1/* 2 * Copyright 2010-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#include "bcc/Compiler.h" 18 19#include <llvm/Analysis/Passes.h> 20#include <llvm/CodeGen/RegAllocRegistry.h> 21#include <llvm/Module.h> 22#include <llvm/PassManager.h> 23#include <llvm/Support/TargetRegistry.h> 24#include <llvm/Support/raw_ostream.h> 25#include <llvm/Target/TargetData.h> 26#include <llvm/Target/TargetMachine.h> 27#include <llvm/Transforms/IPO.h> 28#include <llvm/Transforms/Scalar.h> 29 30#include "bcc/Script.h" 31#include "bcc/Source.h" 32#include "bcc/Support/CompilerConfig.h" 33#include "bcc/Support/Log.h" 34#include "bcc/Support/OutputFile.h" 35 36using namespace bcc; 37 38const char *Compiler::GetErrorString(enum ErrorCode pErrCode) { 39 static const char *ErrorString[] = { 40 /* kSuccess */ 41 "Successfully compiled.", 42 /* kInvalidConfigNoTarget */ 43 "Invalid compiler config supplied (getTarget() returns NULL.) " 44 "(missing call to CompilerConfig::initialize()?)", 45 /* kErrCreateTargetMachine */ 46 "Failed to create llvm::TargetMachine.", 47 /* kErrSwitchTargetMachine */ 48 "Failed to switch llvm::TargetMachine.", 49 /* kErrNoTargetMachine */ 50 "Failed to compile the script since there's no available TargetMachine." 51 " (missing call to Compiler::config()?)", 52 /* kErrTargetDataNoMemory */ 53 "Out of memory when create TargetData during compilation.", 54 /* kErrMaterialization */ 55 "Failed to materialize the module.", 56 /* kErrInvalidOutputFileState */ 57 "Supplied output file was invalid (in the error state.)", 58 /* kErrPrepareOutput */ 59 "Failed to prepare file for output.", 60 /* kPrepareCodeGenPass */ 61 "Failed to construct pass list for code-generation.", 62 63 /* kErrHookBeforeAddLTOPasses */ 64 "Error occurred during beforeAddLTOPasses() in subclass.", 65 /* kErrHookAfterAddLTOPasses */ 66 "Error occurred during afterAddLTOPasses() in subclass.", 67 /* kErrHookBeforeExecuteLTOPasses */ 68 "Error occurred during beforeExecuteLTOPasses() in subclass.", 69 /* kErrHookAfterExecuteLTOPasses */ 70 "Error occurred during afterExecuteLTOPasses() in subclass.", 71 72 /* kErrHookBeforeAddCodeGenPasses */ 73 "Error occurred during beforeAddCodeGenPasses() in subclass.", 74 /* kErrHookAfterAddCodeGenPasses */ 75 "Error occurred during afterAddCodeGenPasses() in subclass.", 76 /* kErrHookBeforeExecuteCodeGenPasses */ 77 "Error occurred during beforeExecuteCodeGenPasses() in subclass.", 78 /* kErrHookAfterExecuteCodeGenPasses */ 79 "Error occurred during afterExecuteCodeGenPasses() in subclass.", 80 81 /* kMaxErrorCode */ 82 "(Unknown error code)" 83 }; 84 85 if (pErrCode > kMaxErrorCode) { 86 pErrCode = kMaxErrorCode; 87 } 88 89 return ErrorString[ static_cast<size_t>(pErrCode) ]; 90} 91 92//===----------------------------------------------------------------------===// 93// Instance Methods 94//===----------------------------------------------------------------------===// 95Compiler::Compiler() : mTarget(NULL), mEnableLTO(true) { 96 return; 97} 98 99Compiler::Compiler(const CompilerConfig &pConfig) : mTarget(NULL), 100 mEnableLTO(true) { 101 const std::string &triple = pConfig.getTriple(); 102 103 enum ErrorCode err = config(pConfig); 104 if (err != kSuccess) { 105 ALOGE("%s (%s, features: %s)", GetErrorString(err), 106 triple.c_str(), pConfig.getFeatureString().c_str()); 107 return; 108 } 109 110 return; 111} 112 113enum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) { 114 if (pConfig.getTarget() == NULL) { 115 return kInvalidConfigNoTarget; 116 } 117 118 llvm::TargetMachine *new_target = 119 (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(), 120 pConfig.getCPU(), 121 pConfig.getFeatureString(), 122 pConfig.getTargetOptions(), 123 pConfig.getRelocationModel(), 124 pConfig.getCodeModel(), 125 pConfig.getOptimizationLevel()); 126 127 if (new_target == NULL) { 128 return ((mTarget != NULL) ? kErrSwitchTargetMachine : 129 kErrCreateTargetMachine); 130 } 131 132 // Replace the old TargetMachine. 133 delete mTarget; 134 mTarget = new_target; 135 136 // Adjust register allocation policy according to the optimization level. 137 // createFastRegisterAllocator: fast but bad quality 138 // createLinearScanRegisterAllocator: not so fast but good quality 139 if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) { 140 llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator); 141 } else { 142 llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator); 143 } 144 145 // Relax all machine instructions. 146 mTarget->setMCRelaxAll(true); 147 148 return kSuccess; 149} 150 151Compiler::~Compiler() { 152 delete mTarget; 153} 154 155enum Compiler::ErrorCode Compiler::runLTO(Script &pScript) { 156 llvm::TargetData *target_data = NULL; 157 158 // Pass manager for link-time optimization 159 llvm::PassManager lto_passes; 160 161 // Prepare TargetData target data from Module 162 target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData()); 163 if (target_data == NULL) { 164 return kErrTargetDataNoMemory; 165 } 166 167 // Add TargetData to the pass manager. 168 lto_passes.add(target_data); 169 170 // Invokde "beforeAddLTOPasses" before adding the first pass. 171 if (!beforeAddLTOPasses(pScript, lto_passes)) { 172 return kErrHookBeforeAddLTOPasses; 173 } 174 175 // We now create passes list performing LTO. These are copied from 176 // (including comments) llvm::PassManagerBuilder::populateLTOPassManager(). 177 // Only a subset of these LTO passes are enabled in optimization level 0 as 178 // they interfere with interactive debugging. 179 // 180 // FIXME: Figure out which passes (if any) makes sense for levels 1 and 2. 181 //if ( != llvm::CodeGenOpt::None) { 182 if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) { 183 lto_passes.add(llvm::createGlobalOptimizerPass()); 184 lto_passes.add(llvm::createConstantMergePass()); 185 } else { 186 // Propagate constants at call sites into the functions they call. This 187 // opens opportunities for globalopt (and inlining) by substituting 188 // function pointers passed as arguments to direct uses of functions. 189 lto_passes.add(llvm::createIPSCCPPass()); 190 191 // Now that we internalized some globals, see if we can hack on them! 192 lto_passes.add(llvm::createGlobalOptimizerPass()); 193 194 // Linking modules together can lead to duplicated global constants, only 195 // keep one copy of each constant... 196 lto_passes.add(llvm::createConstantMergePass()); 197 198 // Remove unused arguments from functions... 199 lto_passes.add(llvm::createDeadArgEliminationPass()); 200 201 // Reduce the code after globalopt and ipsccp. Both can open up 202 // significant simplification opportunities, and both can propagate 203 // functions through function pointers. When this happens, we often have 204 // to resolve varargs calls, etc, so let instcombine do this. 205 lto_passes.add(llvm::createInstructionCombiningPass()); 206 207 // Inline small functions 208 lto_passes.add(llvm::createFunctionInliningPass()); 209 210 // Remove dead EH info. 211 lto_passes.add(llvm::createPruneEHPass()); 212 213 // Internalize the globals again after inlining 214 lto_passes.add(llvm::createGlobalOptimizerPass()); 215 216 // Remove dead functions. 217 lto_passes.add(llvm::createGlobalDCEPass()); 218 219 // If we didn't decide to inline a function, check to see if we can 220 // transform it to pass arguments by value instead of by reference. 221 lto_passes.add(llvm::createArgumentPromotionPass()); 222 223 // The IPO passes may leave cruft around. Clean up after them. 224 lto_passes.add(llvm::createInstructionCombiningPass()); 225 lto_passes.add(llvm::createJumpThreadingPass()); 226 227 // Break up allocas 228 lto_passes.add(llvm::createScalarReplAggregatesPass()); 229 230 // Run a few AA driven optimizations here and now, to cleanup the code. 231 lto_passes.add(llvm::createFunctionAttrsPass()); // Add nocapture. 232 lto_passes.add(llvm::createGlobalsModRefPass()); // IP alias analysis. 233 234 // Hoist loop invariants. 235 lto_passes.add(llvm::createLICMPass()); 236 237 // Remove redundancies. 238 lto_passes.add(llvm::createGVNPass()); 239 240 // Remove dead memcpys. 241 lto_passes.add(llvm::createMemCpyOptPass()); 242 243 // Nuke dead stores. 244 lto_passes.add(llvm::createDeadStoreEliminationPass()); 245 246 // Cleanup and simplify the code after the scalar optimizations. 247 lto_passes.add(llvm::createInstructionCombiningPass()); 248 249 lto_passes.add(llvm::createJumpThreadingPass()); 250 251 // Delete basic blocks, which optimization passes may have killed. 252 lto_passes.add(llvm::createCFGSimplificationPass()); 253 254 // Now that we have optimized the program, discard unreachable functions. 255 lto_passes.add(llvm::createGlobalDCEPass()); 256 } 257 258 // Invokde "afterAddLTOPasses" after pass manager finished its 259 // construction. 260 if (!afterAddLTOPasses(pScript, lto_passes)) { 261 return kErrHookAfterAddLTOPasses; 262 } 263 264 // Invokde "beforeExecuteLTOPasses" before executing the passes. 265 if (!beforeExecuteLTOPasses(pScript, lto_passes)) { 266 return kErrHookBeforeExecuteLTOPasses; 267 } 268 269 lto_passes.run(pScript.getSource().getModule()); 270 271 // Invokde "afterExecuteLTOPasses" before returning. 272 if (!afterExecuteLTOPasses(pScript)) { 273 return kErrHookAfterExecuteLTOPasses; 274 } 275 276 return kSuccess; 277} 278 279enum Compiler::ErrorCode Compiler::runCodeGen(Script &pScript, 280 llvm::raw_ostream &pResult) { 281 llvm::TargetData *target_data; 282 llvm::MCContext *mc_context = NULL; 283 284 // Create pass manager for MC code generation. 285 llvm::PassManager codegen_passes; 286 287 // Prepare TargetData target data from Module 288 target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData()); 289 if (target_data == NULL) { 290 return kErrTargetDataNoMemory; 291 } 292 293 // Add TargetData to the pass manager. 294 codegen_passes.add(target_data); 295 296 // Invokde "beforeAddCodeGenPasses" before adding the first pass. 297 if (!beforeAddCodeGenPasses(pScript, codegen_passes)) { 298 return kErrHookBeforeAddCodeGenPasses; 299 } 300 301 // Add passes to the pass manager to emit machine code through MC layer. 302 if (mTarget->addPassesToEmitMC(codegen_passes, mc_context, pResult, 303 /* DisableVerify */false)) { 304 return kPrepareCodeGenPass; 305 } 306 307 // Invokde "afterAddCodeGenPasses" after pass manager finished its 308 // construction. 309 if (!afterAddCodeGenPasses(pScript, codegen_passes)) { 310 return kErrHookAfterAddCodeGenPasses; 311 } 312 313 // Invokde "beforeExecuteCodeGenPasses" before executing the passes. 314 if (!beforeExecuteCodeGenPasses(pScript, codegen_passes)) { 315 return kErrHookBeforeExecuteCodeGenPasses; 316 } 317 318 // Execute the pass. 319 codegen_passes.run(pScript.getSource().getModule()); 320 321 // Invokde "afterExecuteCodeGenPasses" before returning. 322 if (!afterExecuteCodeGenPasses(pScript)) { 323 return kErrHookAfterExecuteCodeGenPasses; 324 } 325 326 return kSuccess; 327} 328 329enum Compiler::ErrorCode Compiler::compile(Script &pScript, 330 llvm::raw_ostream &pResult) { 331 llvm::Module &module = pScript.getSource().getModule(); 332 enum ErrorCode err; 333 334 if (mTarget == NULL) { 335 return kErrNoTargetMachine; 336 } 337 338 // Materialize the bitcode module. 339 if (module.getMaterializer() != NULL) { 340 std::string error; 341 // A module with non-null materializer means that it is a lazy-load module. 342 // Materialize it now via invoking MaterializeAllPermanently(). This 343 // function returns false when the materialization is successful. 344 if (module.MaterializeAllPermanently(&error)) { 345 ALOGE("Failed to materialize the module `%s'! (%s)", 346 module.getModuleIdentifier().c_str(), error.c_str()); 347 return kErrMaterialization; 348 } 349 } 350 351 if (mEnableLTO && ((err = runLTO(pScript)) != kSuccess)) { 352 return err; 353 } 354 355 if ((err = runCodeGen(pScript, pResult)) != kSuccess) { 356 return err; 357 } 358 359 return kSuccess; 360} 361 362enum Compiler::ErrorCode Compiler::compile(Script &pScript, 363 OutputFile &pResult) { 364 // Check the state of the specified output file. 365 if (pResult.hasError()) { 366 return kErrInvalidOutputFileState; 367 } 368 369 // Open the output file decorated in llvm::raw_ostream. 370 llvm::raw_ostream *out = pResult.dup(); 371 if (out == NULL) { 372 return kErrPrepareOutput; 373 } 374 375 // Delegate the request. 376 enum Compiler::ErrorCode err = compile(pScript, *out); 377 378 // Close the output before return. 379 delete out; 380 381 return err; 382} 383