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