Compiler.cpp revision 9ddeb6b4afb1c3366fd4f95d6d31b3e221f46c85
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 "Compiler.h" 18 19#include "Config.h" 20#include <bcinfo/MetadataExtractor.h> 21 22#if USE_DISASSEMBLER 23#include "Disassembler/Disassembler.h" 24#endif 25 26#include "DebugHelper.h" 27#include "FileHandle.h" 28#include "Runtime.h" 29#include "ScriptCompiled.h" 30#include "Sha1Helper.h" 31#include "CompilerOption.h" 32 33#if USE_MCJIT 34#include "librsloader.h" 35#endif 36 37#include "Transforms/BCCTransforms.h" 38 39#include "llvm/ADT/StringRef.h" 40 41#include "llvm/Analysis/Passes.h" 42 43#include "llvm/CodeGen/Passes.h" 44#include "llvm/CodeGen/RegAllocRegistry.h" 45#include "llvm/CodeGen/SchedulerRegistry.h" 46 47#include "llvm/MC/MCContext.h" 48#include "llvm/MC/SubtargetFeature.h" 49 50#include "llvm/Transforms/IPO.h" 51#include "llvm/Transforms/Scalar.h" 52 53#include "llvm/Target/TargetData.h" 54#include "llvm/Target/TargetMachine.h" 55 56#include "llvm/Support/ErrorHandling.h" 57#include "llvm/Support/FormattedStream.h" 58#include "llvm/Support/TargetRegistry.h" 59#include "llvm/Support/TargetSelect.h" 60#include "llvm/Support/raw_ostream.h" 61 62#include "llvm/Constants.h" 63#include "llvm/GlobalValue.h" 64#include "llvm/Linker.h" 65#include "llvm/LLVMContext.h" 66#include "llvm/Module.h" 67#include "llvm/PassManager.h" 68#include "llvm/Type.h" 69#include "llvm/Value.h" 70 71#include <errno.h> 72#include <sys/file.h> 73#include <sys/stat.h> 74#include <sys/types.h> 75#include <unistd.h> 76 77#include <string.h> 78 79#include <algorithm> 80#include <iterator> 81#include <string> 82#include <vector> 83 84extern char* gDebugDumpDirectory; 85 86namespace bcc { 87 88////////////////////////////////////////////////////////////////////////////// 89// BCC Compiler Static Variables 90////////////////////////////////////////////////////////////////////////////// 91 92bool Compiler::GlobalInitialized = false; 93 94 95#if !defined(__HOST__) 96 #define TARGET_TRIPLE_STRING DEFAULT_TARGET_TRIPLE_STRING 97#else 98// In host TARGET_TRIPLE_STRING is a variable to allow cross-compilation. 99 #if defined(__cplusplus) 100 extern "C" { 101 #endif 102 char *TARGET_TRIPLE_STRING = (char*)DEFAULT_TARGET_TRIPLE_STRING; 103 #if defined(__cplusplus) 104 }; 105 #endif 106#endif 107 108// Code generation optimization level for the compiler 109llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel; 110 111std::string Compiler::Triple; 112llvm::Triple::ArchType Compiler::ArchType; 113 114std::string Compiler::CPU; 115 116std::vector<std::string> Compiler::Features; 117 118 119////////////////////////////////////////////////////////////////////////////// 120// Compiler 121////////////////////////////////////////////////////////////////////////////// 122 123void Compiler::GlobalInitialization() { 124 if (GlobalInitialized) { 125 return; 126 } 127 128#if defined(PROVIDE_ARM_CODEGEN) 129 LLVMInitializeARMAsmPrinter(); 130 LLVMInitializeARMTargetMC(); 131 LLVMInitializeARMTargetInfo(); 132 LLVMInitializeARMTarget(); 133#endif 134 135#if defined(PROVIDE_MIPS_CODEGEN) 136 LLVMInitializeMipsAsmPrinter(); 137 LLVMInitializeMipsTargetMC(); 138 LLVMInitializeMipsTargetInfo(); 139 LLVMInitializeMipsTarget(); 140#endif 141 142#if defined(PROVIDE_X86_CODEGEN) 143 LLVMInitializeX86AsmPrinter(); 144 LLVMInitializeX86TargetMC(); 145 LLVMInitializeX86TargetInfo(); 146 LLVMInitializeX86Target(); 147#endif 148 149#if USE_DISASSEMBLER 150 InitializeDisassembler(); 151#endif 152 153 // if (!llvm::llvm_is_multithreaded()) 154 // llvm::llvm_start_multithreaded(); 155 156 // Set Triple, CPU and Features here 157 Triple = TARGET_TRIPLE_STRING; 158 159 // Determine ArchType 160#if defined(__HOST__) 161 { 162 std::string Err; 163 llvm::Target const *Target = llvm::TargetRegistry::lookupTarget(Triple, Err); 164 if (Target != NULL) { 165 ArchType = llvm::Triple::getArchTypeForLLVMName(Target->getName()); 166 } else { 167 ArchType = llvm::Triple::UnknownArch; 168 ALOGE("%s", Err.c_str()); 169 } 170 } 171#elif defined(DEFAULT_ARM_CODEGEN) 172 ArchType = llvm::Triple::arm; 173#elif defined(DEFAULT_MIPS_CODEGEN) 174 ArchType = llvm::Triple::mipsel; 175#elif defined(DEFAULT_X86_CODEGEN) 176 ArchType = llvm::Triple::x86; 177#elif defined(DEFAULT_X86_64_CODEGEN) 178 ArchType = llvm::Triple::x86_64; 179#else 180 ArchType = llvm::Triple::UnknownArch; 181#endif 182 183 if ((ArchType == llvm::Triple::arm) || (ArchType == llvm::Triple::thumb)) { 184# if defined(ARCH_ARM_HAVE_VFP) 185 Features.push_back("+vfp3"); 186# if !defined(ARCH_ARM_HAVE_VFP_D32) 187 Features.push_back("+d16"); 188# endif 189# endif 190 191# if defined(ARCH_ARM_HAVE_NEON) 192 Features.push_back("+neon"); 193 Features.push_back("+neonfp"); 194# else 195 Features.push_back("-neon"); 196 Features.push_back("-neonfp"); 197# endif 198 199// FIXME(all): Turn NEON back on after debugging the rebase. 200# if 1 || defined(DISABLE_ARCH_ARM_HAVE_NEON) 201 Features.push_back("-neon"); 202 Features.push_back("-neonfp"); 203# endif 204 } 205 206 // Register the scheduler 207 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler); 208 209#if USE_CACHE 210 // Read in SHA1 checksum of libbcc and libRS. 211 readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1); 212 213 calcFileSHA1(sha1LibRS, pathLibRS); 214#endif 215 216 GlobalInitialized = true; 217} 218 219 220void Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) { 221 std::string *Error = static_cast<std::string*>(UserData); 222 Error->assign(Message); 223 ALOGE("%s", Message.c_str()); 224 exit(1); 225} 226 227 228Compiler::Compiler(ScriptCompiled *result) 229 : mpResult(result), 230#if USE_MCJIT 231 mRSExecutable(NULL), 232#endif 233 mpSymbolLookupFn(NULL), 234 mpSymbolLookupContext(NULL), 235 mModule(NULL), 236 mHasLinked(false) /* Turn off linker */ { 237 llvm::remove_fatal_error_handler(); 238 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError); 239 return; 240} 241 242 243int Compiler::linkModule(llvm::Module *moduleWith) { 244 if (llvm::Linker::LinkModules(mModule, moduleWith, 245 llvm::Linker::PreserveSource, 246 &mError) != 0) { 247 return hasError(); 248 } 249 250 // Everything for linking should be settled down here with no error occurs 251 mHasLinked = true; 252 return hasError(); 253} 254 255 256int Compiler::compile(const CompilerOption &option) { 257 llvm::Target const *Target = NULL; 258 llvm::TargetData *TD = NULL; 259 llvm::TargetMachine *TM = NULL; 260 261 std::string FeaturesStr; 262 263 if (mModule == NULL) // No module was loaded 264 return 0; 265 266 bcinfo::MetadataExtractor ME(mModule); 267 ME.extract(); 268 269 size_t VarCount = ME.getExportVarCount(); 270 size_t FuncCount = ME.getExportFuncCount(); 271 size_t ForEachSigCount = ME.getExportForEachSignatureCount(); 272 size_t ObjectSlotCount = ME.getObjectSlotCount(); 273 size_t PragmaCount = ME.getPragmaCount(); 274 275 std::vector<std::string> &VarNameList = mpResult->mExportVarsName; 276 std::vector<std::string> &FuncNameList = mpResult->mExportFuncsName; 277 std::vector<std::string> &ForEachExpandList = mpResult->mExportForEachName; 278 std::vector<std::string> ForEachNameList; 279 std::vector<uint32_t> ForEachSigList; 280 std::vector<const char*> ExportSymbols; 281 282 // Defaults to maximum optimization level from MetadataExtractor. 283 int OptimizationLevel = ME.getOptimizationLevel(); 284 285 if (OptimizationLevel == 0) { 286 CodeGenOptLevel = llvm::CodeGenOpt::None; 287 } else if (OptimizationLevel == 1) { 288 CodeGenOptLevel = llvm::CodeGenOpt::Less; 289 } else if (OptimizationLevel == 2) { 290 CodeGenOptLevel = llvm::CodeGenOpt::Default; 291 } else if (OptimizationLevel == 3) { 292 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive; 293 } 294 295 // not the best place for this, but we need to set the register allocation 296 // policy after we read the optimization_level metadata from the bitcode 297 298 // Register allocation policy: 299 // createFastRegisterAllocator: fast but bad quality 300 // createLinearScanRegisterAllocator: not so fast but good quality 301 llvm::RegisterRegAlloc::setDefault 302 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ? 303 llvm::createFastRegisterAllocator : 304 llvm::createGreedyRegisterAllocator); 305 306 // Find LLVM Target 307 Target = llvm::TargetRegistry::lookupTarget(Triple, mError); 308 if (hasError()) 309 goto on_bcc_compile_error; 310 311 if (!CPU.empty() || !Features.empty()) { 312 llvm::SubtargetFeatures F; 313 314 for (std::vector<std::string>::const_iterator 315 I = Features.begin(), E = Features.end(); I != E; I++) { 316 F.AddFeature(*I); 317 } 318 319 FeaturesStr = F.getString(); 320 } 321 322 // Create LLVM Target Machine 323 TM = Target->createTargetMachine(Triple, CPU, FeaturesStr, 324 option.TargetOpt, 325 option.RelocModelOpt, 326 option.CodeModelOpt); 327 328 if (TM == NULL) { 329 setError("Failed to create target machine implementation for the" 330 " specified triple '" + Triple + "'"); 331 goto on_bcc_compile_error; 332 } 333 334 // Get target data from Module 335 TD = new llvm::TargetData(mModule); 336 337 // Read pragma information from MetadataExtractor 338 if (PragmaCount) { 339 ScriptCompiled::PragmaList &PragmaPairs = mpResult->mPragmas; 340 const char **PragmaKeys = ME.getPragmaKeyList(); 341 const char **PragmaValues = ME.getPragmaValueList(); 342 for (size_t i = 0; i < PragmaCount; i++) { 343 PragmaPairs.push_back(std::make_pair(PragmaKeys[i], PragmaValues[i])); 344 } 345 } 346 347 if (VarCount) { 348 const char **VarNames = ME.getExportVarNameList(); 349 for (size_t i = 0; i < VarCount; i++) { 350 VarNameList.push_back(VarNames[i]); 351 ExportSymbols.push_back(VarNames[i]); 352 } 353 } 354 355 if (FuncCount) { 356 const char **FuncNames = ME.getExportFuncNameList(); 357 for (size_t i = 0; i < FuncCount; i++) { 358 FuncNameList.push_back(FuncNames[i]); 359 ExportSymbols.push_back(FuncNames[i]); 360 } 361 } 362 363 if (ForEachSigCount) { 364 const char **ForEachNames = ME.getExportForEachNameList(); 365 const uint32_t *ForEachSigs = ME.getExportForEachSignatureList(); 366 for (size_t i = 0; i < ForEachSigCount; i++) { 367 std::string Name(ForEachNames[i]); 368 ForEachNameList.push_back(Name); 369 ForEachExpandList.push_back(Name + ".expand"); 370 ForEachSigList.push_back(ForEachSigs[i]); 371 } 372 373 // Need to wait until ForEachExpandList is fully populated to fill in 374 // exported symbols. 375 for (size_t i = 0; i < ForEachSigCount; i++) { 376 ExportSymbols.push_back(ForEachExpandList[i].c_str()); 377 } 378 } 379 380 if (ObjectSlotCount) { 381 ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots; 382 const uint32_t *ObjectSlots = ME.getObjectSlotList(); 383 for (size_t i = 0; i < ObjectSlotCount; i++) { 384 objectSlotList.push_back(ObjectSlots[i]); 385 } 386 } 387 388 runInternalPasses(ForEachNameList, ForEachSigList); 389 390 // Perform link-time optimization if we have multiple modules 391 if (mHasLinked) { 392 runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel); 393 } 394 395 // Perform code generation 396#if USE_MCJIT 397 if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) { 398 goto on_bcc_compile_error; 399 } 400 401 if (!option.LoadAfterCompile) 402 return 0; 403 404 // Load the ELF Object 405 mRSExecutable = 406 rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(), 407 mEmittedELFExecutable.size(), 408 &resolveSymbolAdapter, this); 409 410 if (!mRSExecutable) { 411 setError("Fail to load emitted ELF relocatable file"); 412 goto on_bcc_compile_error; 413 } 414 415 rsloaderUpdateSectionHeaders(mRSExecutable, 416 (unsigned char*) mEmittedELFExecutable.begin()); 417 418 // Once the ELF object has been loaded, populate the various slots for RS 419 // with the appropriate relocated addresses. 420 if (VarCount) { 421 ScriptCompiled::ExportVarList &VarList = mpResult->mExportVars; 422 for (size_t i = 0; i < VarCount; i++) { 423 VarList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 424 VarNameList[i].c_str())); 425 } 426 } 427 428 if (FuncCount) { 429 ScriptCompiled::ExportFuncList &FuncList = mpResult->mExportFuncs; 430 for (size_t i = 0; i < FuncCount; i++) { 431 FuncList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 432 FuncNameList[i].c_str())); 433 } 434 } 435 436 if (ForEachSigCount) { 437 ScriptCompiled::ExportForEachList &ForEachList = mpResult->mExportForEach; 438 for (size_t i = 0; i < ForEachSigCount; i++) { 439 ForEachList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 440 ForEachExpandList[i].c_str())); 441 } 442 } 443 444#if DEBUG_MCJIT_DISASSEMBLER 445 { 446 // Get MC codegen emitted function name list 447 size_t func_list_size = rsloaderGetFuncCount(mRSExecutable); 448 std::vector<char const *> func_list(func_list_size, NULL); 449 rsloaderGetFuncNameList(mRSExecutable, func_list_size, &*func_list.begin()); 450 451 // Disassemble each function 452 for (size_t i = 0; i < func_list_size; ++i) { 453 void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]); 454 if (func) { 455 size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]); 456 Disassemble(DEBUG_MCJIT_DISASSEMBLER_FILE, 457 Target, TM, func_list[i], (unsigned char const *)func, size); 458 } 459 } 460 } 461#endif 462#endif 463 464on_bcc_compile_error: 465 // ALOGE("on_bcc_compiler_error"); 466 if (TD) { 467 delete TD; 468 } 469 470 if (TM) { 471 delete TM; 472 } 473 474 if (mError.empty()) { 475 return 0; 476 } 477 478 // ALOGE(getErrorMessage()); 479 return 1; 480} 481 482 483#if USE_MCJIT 484int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) { 485 // Decorate mEmittedELFExecutable with formatted ostream 486 llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable); 487 488 // Relax all machine instructions 489 TM->setMCRelaxAll(/* RelaxAll= */ true); 490 491 // Create MC code generation pass manager 492 llvm::PassManager MCCodeGenPasses; 493 494 // Add TargetData to MC code generation pass manager 495 MCCodeGenPasses.add(TD); 496 497 // Add MC code generation passes to pass manager 498 llvm::MCContext *Ctx = NULL; 499 if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) { 500 setError("Fail to add passes to emit file"); 501 return 1; 502 } 503 504 MCCodeGenPasses.run(*mModule); 505 OutSVOS.flush(); 506 return 0; 507} 508#endif // USE_MCJIT 509 510int Compiler::runInternalPasses(std::vector<std::string>& Names, 511 std::vector<uint32_t>& Signatures) { 512 llvm::PassManager BCCPasses; 513 514 // Expand ForEach on CPU path to reduce launch overhead. 515 BCCPasses.add(createForEachExpandPass(Names, Signatures)); 516 517 BCCPasses.run(*mModule); 518 519 return 0; 520} 521 522int Compiler::runLTO(llvm::TargetData *TD, 523 std::vector<const char*>& ExportSymbols, 524 llvm::CodeGenOpt::Level OptimizationLevel) { 525 // Note: ExportSymbols is a workaround for getting all exported variable, 526 // function, and kernel names. 527 // We should refine it soon. 528 529 // TODO(logan): Remove this after we have finished the 530 // bccMarkExternalSymbol API. 531 532 // root(), init(), and .rs.dtor() are born to be exported 533 ExportSymbols.push_back("root"); 534 ExportSymbols.push_back("init"); 535 ExportSymbols.push_back(".rs.dtor"); 536 537 // User-defined exporting symbols 538 std::vector<char const *> const &UserDefinedExternalSymbols = 539 mpResult->getUserDefinedExternalSymbols(); 540 541 std::copy(UserDefinedExternalSymbols.begin(), 542 UserDefinedExternalSymbols.end(), 543 std::back_inserter(ExportSymbols)); 544 545 llvm::PassManager LTOPasses; 546 547 // Add TargetData to LTO passes 548 LTOPasses.add(TD); 549 550 // We now create passes list performing LTO. These are copied from 551 // (including comments) llvm::createStandardLTOPasses(). 552 // Only a subset of these LTO passes are enabled in optimization level 0 553 // as they interfere with interactive debugging. 554 // FIXME: figure out which passes (if any) makes sense for levels 1 and 2 555 556 if (OptimizationLevel != llvm::CodeGenOpt::None) { 557 // Internalize all other symbols not listed in ExportSymbols 558 LTOPasses.add(llvm::createInternalizePass(ExportSymbols)); 559 560 // Propagate constants at call sites into the functions they call. This 561 // opens opportunities for globalopt (and inlining) by substituting 562 // function pointers passed as arguments to direct uses of functions. 563 LTOPasses.add(llvm::createIPSCCPPass()); 564 565 // Now that we internalized some globals, see if we can hack on them! 566 LTOPasses.add(llvm::createGlobalOptimizerPass()); 567 568 // Linking modules together can lead to duplicated global constants, only 569 // keep one copy of each constant... 570 LTOPasses.add(llvm::createConstantMergePass()); 571 572 // Remove unused arguments from functions... 573 LTOPasses.add(llvm::createDeadArgEliminationPass()); 574 575 // Reduce the code after globalopt and ipsccp. Both can open up 576 // significant simplification opportunities, and both can propagate 577 // functions through function pointers. When this happens, we often have 578 // to resolve varargs calls, etc, so let instcombine do this. 579 LTOPasses.add(llvm::createInstructionCombiningPass()); 580 581 // Inline small functions 582 LTOPasses.add(llvm::createFunctionInliningPass()); 583 584 // Remove dead EH info. 585 LTOPasses.add(llvm::createPruneEHPass()); 586 587 // Internalize the globals again after inlining 588 LTOPasses.add(llvm::createGlobalOptimizerPass()); 589 590 // Remove dead functions. 591 LTOPasses.add(llvm::createGlobalDCEPass()); 592 593 // If we didn't decide to inline a function, check to see if we can 594 // transform it to pass arguments by value instead of by reference. 595 LTOPasses.add(llvm::createArgumentPromotionPass()); 596 597 // The IPO passes may leave cruft around. Clean up after them. 598 LTOPasses.add(llvm::createInstructionCombiningPass()); 599 LTOPasses.add(llvm::createJumpThreadingPass()); 600 601 // Break up allocas 602 LTOPasses.add(llvm::createScalarReplAggregatesPass()); 603 604 // Run a few AA driven optimizations here and now, to cleanup the code. 605 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture. 606 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis. 607 608 // Hoist loop invariants. 609 LTOPasses.add(llvm::createLICMPass()); 610 611 // Remove redundancies. 612 LTOPasses.add(llvm::createGVNPass()); 613 614 // Remove dead memcpys. 615 LTOPasses.add(llvm::createMemCpyOptPass()); 616 617 // Nuke dead stores. 618 LTOPasses.add(llvm::createDeadStoreEliminationPass()); 619 620 // Cleanup and simplify the code after the scalar optimizations. 621 LTOPasses.add(llvm::createInstructionCombiningPass()); 622 623 LTOPasses.add(llvm::createJumpThreadingPass()); 624 625 // Delete basic blocks, which optimization passes may have killed. 626 LTOPasses.add(llvm::createCFGSimplificationPass()); 627 628 // Now that we have optimized the program, discard unreachable functions. 629 LTOPasses.add(llvm::createGlobalDCEPass()); 630 631 } else { 632 LTOPasses.add(llvm::createInternalizePass(ExportSymbols)); 633 LTOPasses.add(llvm::createGlobalOptimizerPass()); 634 LTOPasses.add(llvm::createConstantMergePass()); 635 } 636 637 LTOPasses.run(*mModule); 638 639#if ANDROID_ENGINEERING_BUILD 640 if (0 != gDebugDumpDirectory) { 641 std::string errs; 642 std::string Filename(gDebugDumpDirectory); 643 Filename += "/post-lto-module.ll"; 644 llvm::raw_fd_ostream FS(Filename.c_str(), errs); 645 mModule->print(FS, 0); 646 FS.close(); 647 } 648#endif 649 650 return 0; 651} 652 653 654#if USE_MCJIT 655void *Compiler::getSymbolAddress(char const *name) { 656 return rsloaderGetSymbolAddress(mRSExecutable, name); 657} 658#endif 659 660 661#if USE_MCJIT 662void *Compiler::resolveSymbolAdapter(void *context, char const *name) { 663 Compiler *self = reinterpret_cast<Compiler *>(context); 664 665 if (void *Addr = FindRuntimeFunction(name)) { 666 return Addr; 667 } 668 669 if (self->mpSymbolLookupFn) { 670 if (void *Addr = self->mpSymbolLookupFn(self->mpSymbolLookupContext, name)) { 671 return Addr; 672 } 673 } 674 675 ALOGE("Unable to resolve symbol: %s\n", name); 676 return NULL; 677} 678#endif 679 680 681Compiler::~Compiler() { 682#if USE_MCJIT 683 rsloaderDisposeExec(mRSExecutable); 684#endif 685 686 // llvm::llvm_shutdown(); 687} 688 689 690} // namespace bcc 691