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