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