Compiler.cpp revision 4a68b1cb89df9507584a51c3444aff99347afb74
11f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan/* 2db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Copyright 2010-2012, The Android Open Source Project 31f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * 41f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * Licensed under the Apache License, Version 2.0 (the "License"); 51f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * you may not use this file except in compliance with the License. 61f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * You may obtain a copy of the License at 71f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * 81f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * http://www.apache.org/licenses/LICENSE-2.0 91f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * 101f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * Unless required by applicable law or agreed to in writing, software 111f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * distributed under the License is distributed on an "AS IS" BASIS, 121f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * See the License for the specific language governing permissions and 141f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan * limitations under the License. 151f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan */ 161f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 172f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "Compiler.h" 181f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 194a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "Config.h" 204a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <bcinfo/MetadataExtractor.h> 214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if USE_DISASSEMBLER 234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "Disassembler/Disassembler.h" 244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 254a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 264a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "BCCRuntimeSymbolResolver.h" 272f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "DebugHelper.h" 284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "ScriptCompiled.h" 294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "Sha1Helper.h" 304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "CompilerOption.h" 314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "SymbolResolverProxy.h" 324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "SymbolResolvers.h" 3351001b86751c1ca36307eddc44a65336079fb698Joseph Wen 344a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "librsloader.h" 351f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "RSTransforms.h" 374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/ADT/StringRef.h" 394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Analysis/Passes.h" 414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/CodeGen/Passes.h" 434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/CodeGen/RegAllocRegistry.h" 444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/CodeGen/SchedulerRegistry.h" 454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/MC/MCContext.h" 474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/MC/SubtargetFeature.h" 484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Transforms/IPO.h" 504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Transforms/Scalar.h" 514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Target/TargetData.h" 534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Target/TargetMachine.h" 544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Support/ErrorHandling.h" 564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Support/FormattedStream.h" 574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Support/TargetRegistry.h" 584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Support/TargetSelect.h" 594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Support/raw_ostream.h" 604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Constants.h" 624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/GlobalValue.h" 634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Linker.h" 644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/LLVMContext.h" 654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Module.h" 664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/PassManager.h" 674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Type.h" 684a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include "llvm/Value.h" 694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 704a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <errno.h> 714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <sys/file.h> 724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <sys/stat.h> 734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <sys/types.h> 744a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <unistd.h> 754a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <string.h> 774a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 784a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <algorithm> 794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <iterator> 804a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <string> 814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#include <vector> 824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 834a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesextern char* gDebugDumpDirectory; 844a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesnamespace bcc { 864a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 874a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines////////////////////////////////////////////////////////////////////////////// 884a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines// BCC Compiler Static Variables 894a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines////////////////////////////////////////////////////////////////////////////// 904a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 914a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesbool Compiler::GlobalInitialized = false; 921f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 93fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if !defined(__HOST__) 954a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines #define TARGET_TRIPLE_STRING DEFAULT_TARGET_TRIPLE_STRING 964a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#else 974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines// In host TARGET_TRIPLE_STRING is a variable to allow cross-compilation. 984a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines #if defined(__cplusplus) 994a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines extern "C" { 1004a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines #endif 1014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines char *TARGET_TRIPLE_STRING = (char*)DEFAULT_TARGET_TRIPLE_STRING; 1024a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines #if defined(__cplusplus) 1034a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines }; 1044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines #endif 1054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1074a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines// Code generation optimization level for the compiler 1084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesllvm::CodeGenOpt::Level Compiler::CodeGenOptLevel; 1094a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1104a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesstd::string Compiler::Triple; 1114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesllvm::Triple::ArchType Compiler::ArchType; 1124a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1134a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesstd::string Compiler::CPU; 1144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1154a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesstd::vector<std::string> Compiler::Features; 1164a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1174a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1184a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines////////////////////////////////////////////////////////////////////////////// 1194a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines// Compiler 1204a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines////////////////////////////////////////////////////////////////////////////// 1214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesvoid Compiler::GlobalInitialization() { 1234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (GlobalInitialized) { 124fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return; 125fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 1261f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 1274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if defined(PROVIDE_ARM_CODEGEN) 1284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeARMAsmPrinter(); 1294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeARMTargetMC(); 1304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeARMTargetInfo(); 1314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeARMTarget(); 1324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1334a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1344a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if defined(PROVIDE_MIPS_CODEGEN) 1354a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeMipsAsmPrinter(); 1364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeMipsTargetMC(); 1374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeMipsTargetInfo(); 1384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeMipsTarget(); 1394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if defined(PROVIDE_X86_CODEGEN) 1424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeX86AsmPrinter(); 1434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeX86TargetMC(); 1444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeX86TargetInfo(); 1454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LLVMInitializeX86Target(); 1464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if USE_DISASSEMBLER 1494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines InitializeDisassembler(); 1504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // if (!llvm::llvm_is_multithreaded()) 1534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // llvm::llvm_start_multithreaded(); 1544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Set Triple, CPU and Features here 1564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Triple = TARGET_TRIPLE_STRING; 1574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Determine ArchType 1594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if defined(__HOST__) 1604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines { 1614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::string Err; 1624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::Target const *Target = llvm::TargetRegistry::lookupTarget(Triple, Err); 1634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (Target != NULL) { 1644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::getArchTypeForLLVMName(Target->getName()); 1654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } else { 1664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::UnknownArch; 1674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ALOGE("%s", Err.c_str()); 1684a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 1694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 1704a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#elif defined(DEFAULT_ARM_CODEGEN) 1714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::arm; 1724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#elif defined(DEFAULT_MIPS_CODEGEN) 1734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::mipsel; 1744a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#elif defined(DEFAULT_X86_CODEGEN) 1754a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::x86; 1764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#elif defined(DEFAULT_X86_64_CODEGEN) 1774a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::x86_64; 1784a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#else 1794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ArchType = llvm::Triple::UnknownArch; 1804a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 1814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if ((ArchType == llvm::Triple::arm) || (ArchType == llvm::Triple::thumb)) { 1834a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# if defined(ARCH_ARM_HAVE_VFP) 1844a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("+vfp3"); 1854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# if !defined(ARCH_ARM_HAVE_VFP_D32) 1864a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("+d16"); 1874a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# endif 1884a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# endif 1894a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1904a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# if defined(ARCH_ARM_HAVE_NEON) 1914a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("+neon"); 1924a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("+neonfp"); 1934a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# else 1944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neon"); 1954a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neonfp"); 1964a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# endif 1974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 1984a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines// FIXME(all): Turn NEON back on after debugging the rebase. 1994a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# if 1 || defined(DISABLE_ARCH_ARM_HAVE_NEON) 2004a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neon"); 2014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neonfp"); 2024a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines# endif 2034a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 2044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Register the scheduler 2064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler); 2074a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Read in SHA1 checksum of libbcc and libRS. 2094a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1); 2104a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines calcFileSHA1(sha1LibRS, pathLibRS); 2124a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2134a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines GlobalInitialized = true; 2144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 2154a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2164a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2174a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesvoid Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) { 2184a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::string *Error = static_cast<std::string*>(UserData); 2194a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Error->assign(Message); 2204a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ALOGE("%s", Message.c_str()); 2214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines exit(1); 2224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 2234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2254a68b1cb89df9507584a51c3444aff99347afb74Stephen HinesCompiler::Compiler(ScriptCompiled *result) 2264a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines : mpResult(result), 2274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mRSExecutable(NULL), 2284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mpSymbolLookupFn(NULL), 2294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mpSymbolLookupContext(NULL), 2304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mModule(NULL) { 2314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::remove_fatal_error_handler(); 2324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::install_fatal_error_handler(LLVMErrorHandler, &mError); 2331f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan return; 2341f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 2351f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 2364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesint Compiler::readModule(llvm::Module &pModule) { 2374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mModule = &pModule; 2384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (pModule.getMaterializer() != NULL) { 2394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // A module with non-null materializer means that it is a lazy-load module. 2404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Materialize it now via invoking MaterializeAllPermanently(). This 2414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // function returns false when the materialization is successful. 2424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (pModule.MaterializeAllPermanently(&mError)) { 2434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines setError("Failed to materialize the module `" + 2444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines pModule.getModuleIdentifier() + "'! (" + mError + ")"); 2454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mModule = NULL; 2464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 2471f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan } 2484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return hasError(); 2494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 2501f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 2514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesint Compiler::compile(const CompilerOption &option) { 2524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::Target const *Target = NULL; 2534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::TargetData *TD = NULL; 2544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::TargetMachine *TM = NULL; 2554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::string FeaturesStr; 2574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (mModule == NULL) // No module was loaded 2594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 2604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines bcinfo::MetadataExtractor ME(mModule); 2624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ME.extract(); 2634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t VarCount = ME.getExportVarCount(); 2654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t FuncCount = ME.getExportFuncCount(); 2664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t ForEachSigCount = ME.getExportForEachSignatureCount(); 2674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t ObjectSlotCount = ME.getObjectSlotCount(); 2684a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t PragmaCount = ME.getPragmaCount(); 2694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2704a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<std::string> &VarNameList = mpResult->mExportVarsName; 2714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<std::string> &FuncNameList = mpResult->mExportFuncsName; 2724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<std::string> &ForEachExpandList = mpResult->mExportForEachName; 2734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines RSInfo::ExportForeachFuncListTy ForEachFuncList; 2744a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<const char*> ExportSymbols; 2754a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Defaults to maximum optimization level from MetadataExtractor. 2774a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines uint32_t OptimizationLevel = ME.getOptimizationLevel(); 2784a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 2794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (OptimizationLevel == 0) { 2804a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines CodeGenOptLevel = llvm::CodeGenOpt::None; 2814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } else if (OptimizationLevel == 1) { 2824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines CodeGenOptLevel = llvm::CodeGenOpt::Less; 2834a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } else if (OptimizationLevel == 2) { 2844a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines CodeGenOptLevel = llvm::CodeGenOpt::Default; 2854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } else if (OptimizationLevel == 3) { 2864a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines CodeGenOptLevel = llvm::CodeGenOpt::Aggressive; 287094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 288094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 2894a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // not the best place for this, but we need to set the register allocation 2904a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // policy after we read the optimization_level metadata from the bitcode 291094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 2924a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Register allocation policy: 293094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // createFastRegisterAllocator: fast but bad quality 294094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // createLinearScanRegisterAllocator: not so fast but good quality 2954a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::RegisterRegAlloc::setDefault 2964a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ((CodeGenOptLevel == llvm::CodeGenOpt::None) ? 2974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::createFastRegisterAllocator : 2984a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::createGreedyRegisterAllocator); 2994a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3004a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Find LLVM Target 3014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Target = llvm::TargetRegistry::lookupTarget(Triple, mError); 3024a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (hasError()) 3034a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines goto on_bcc_compile_error; 3044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if defined(ARCH_ARM_HAVE_NEON) 3064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Full-precision means we have to disable NEON 3074a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (ME.getRSFloatPrecision() == bcinfo::RS_FP_Full) { 3084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neon"); 3094a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Features.push_back("-neonfp"); 310da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien } 3114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 312da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 3134a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (!CPU.empty() || !Features.empty()) { 3144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::SubtargetFeatures F; 3151f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 3164a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (std::vector<std::string>::const_iterator 3174a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines I = Features.begin(), E = Features.end(); I != E; I++) { 3184a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines F.AddFeature(*I); 3194a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3201f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 3214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines FeaturesStr = F.getString(); 3224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Create LLVM Target Machine 3254a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines TM = Target->createTargetMachine(Triple, CPU, FeaturesStr, 3264a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines option.TargetOpt, 3274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines option.RelocModelOpt, 3284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines option.CodeModelOpt); 3294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (TM == NULL) { 3314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines setError("Failed to create target machine implementation for the" 3324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines " specified triple '" + Triple + "'"); 3334a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines goto on_bcc_compile_error; 3344a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3354a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Get target data from Module 3374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines TD = new llvm::TargetData(mModule); 3384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Read pragma information from MetadataExtractor 3404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (PragmaCount) { 3414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ScriptCompiled::PragmaList &PragmaPairs = mpResult->mPragmas; 3424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const char **PragmaKeys = ME.getPragmaKeyList(); 3434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const char **PragmaValues = ME.getPragmaValueList(); 3444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < PragmaCount; i++) { 3454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines PragmaPairs.push_back(std::make_pair(PragmaKeys[i], PragmaValues[i])); 3464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (VarCount) { 3504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const char **VarNames = ME.getExportVarNameList(); 3514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < VarCount; i++) { 3524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines VarNameList.push_back(VarNames[i]); 3534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back(VarNames[i]); 3544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (FuncCount) { 3584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const char **FuncNames = ME.getExportFuncNameList(); 3594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < FuncCount; i++) { 3604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines FuncNameList.push_back(FuncNames[i]); 3614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back(FuncNames[i]); 3624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (ForEachSigCount) { 3664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const char **ForEachNames = ME.getExportForEachNameList(); 3674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const uint32_t *ForEachSigs = ME.getExportForEachSignatureList(); 3684a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < ForEachSigCount; i++) { 3694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ForEachFuncList.push_back(std::make_pair(ForEachNames[i], 3704a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ForEachSigs[i])); 3714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ForEachExpandList.push_back(std::string(ForEachNames[i]) + ".expand"); 3724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3744a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Need to wait until ForEachExpandList is fully populated to fill in 3754a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // exported symbols. 3764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < ForEachSigCount; i++) { 3774a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back(ForEachExpandList[i].c_str()); 3784a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3804a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 3814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (ObjectSlotCount) { 3824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots; 3834a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines const uint32_t *ObjectSlots = ME.getObjectSlotList(); 3844a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < ObjectSlotCount; i++) { 3854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines objectSlotList.push_back(ObjectSlots[i]); 3864a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3874a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3881f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 3894a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines runInternalPasses(ForEachFuncList); 390cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines 3914a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Perform link-time optimization if we have multiple modules 3924a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (option.RunLTO) { 3934a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel); 3944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 3957890d437030c1594bc9c9f61fa1e80a57754b078Logan Chien 3964a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Perform code generation 3974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) { 3984a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines goto on_bcc_compile_error; 399fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 4007890d437030c1594bc9c9f61fa1e80a57754b078Logan Chien 4014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (!option.LoadAfterCompile) 4024a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 4034a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Load the ELF Object 4054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines { 4064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines BCCRuntimeSymbolResolver BCCRuntimesResolver; 4074a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LookupFunctionSymbolResolver<void*> RSSymbolResolver(mpSymbolLookupFn, 4084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mpSymbolLookupContext); 4094a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4104a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines SymbolResolverProxy Resolver; 4114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Resolver.chainResolver(BCCRuntimesResolver); 4124a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Resolver.chainResolver(RSSymbolResolver); 413094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 4144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mRSExecutable = 4154a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(), 4164a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mEmittedELFExecutable.size(), 4174a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines SymbolResolverProxy::LookupFunction, &Resolver); 418fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 419094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 4204a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (!mRSExecutable) { 4214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines setError("Fail to load emitted ELF relocatable file"); 4224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines goto on_bcc_compile_error; 4234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4254a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines rsloaderUpdateSectionHeaders(mRSExecutable, 4264a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines (unsigned char*) mEmittedELFExecutable.begin()); 4274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Once the ELF object has been loaded, populate the various slots for RS 4294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // with the appropriate relocated addresses. 4304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (VarCount) { 4314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ScriptCompiled::ExportVarList &VarList = mpResult->mExportVars; 4324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < VarCount; i++) { 4334a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines VarList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 4344a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines VarNameList[i].c_str())); 4354a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (FuncCount) { 4394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ScriptCompiled::ExportFuncList &FuncList = mpResult->mExportFuncs; 4404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < FuncCount; i++) { 4414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines FuncList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 4424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines FuncNameList[i].c_str())); 4434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (ForEachSigCount) { 4474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ScriptCompiled::ExportForEachList &ForEachList = mpResult->mExportForEach; 4484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < ForEachSigCount; i++) { 4494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ForEachList.push_back(rsloaderGetSymbolAddress(mRSExecutable, 4504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ForEachExpandList[i].c_str())); 4514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if DEBUG_MC_DISASSEMBLER 4554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines { 4564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Get MC codegen emitted function name list 4574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t func_list_size = rsloaderGetFuncCount(mRSExecutable); 4584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<char const *> func_list(func_list_size, NULL); 4594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines rsloaderGetFuncNameList(mRSExecutable, func_list_size, &*func_list.begin()); 4604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Disassemble each function 4624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines for (size_t i = 0; i < func_list_size; ++i) { 4634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]); 4644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (func) { 4654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]); 4664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Disassemble(DEBUG_MC_DISASSEMBLER_FILE, 4674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Target, TM, func_list[i], (unsigned char const *)func, size); 4684a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4704a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 4724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hineson_bcc_compile_error: 4744a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // ALOGE("on_bcc_compiler_error"); 4754a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (TD) { 4764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines delete TD; 4774a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4784a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (TM) { 4804a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines delete TM; 4814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4834a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (mError.empty()) { 4844a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 4854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 4864a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4874a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // ALOGE(getErrorMessage()); 4884a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 1; 4894a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 4904a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4914a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4924a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesint Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) { 4934a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Decorate mEmittedELFExecutable with formatted ostream 4944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable); 4954a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4964a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Relax all machine instructions 4974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines TM->setMCRelaxAll(/* RelaxAll= */ true); 4984a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 4994a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Create MC code generation pass manager 5004a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::PassManager MCCodeGenPasses; 5014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5024a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Add TargetData to MC code generation pass manager 5034a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines MCCodeGenPasses.add(TD); 5044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Add MC code generation passes to pass manager 5064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::MCContext *Ctx = NULL; 5074a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) { 5084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines setError("Fail to add passes to emit file"); 5094a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 1; 5104a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } 5114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5124a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines MCCodeGenPasses.run(*mModule); 5134a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines OutSVOS.flush(); 5144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 5154a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 5164a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5174a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesint Compiler::runInternalPasses(RSInfo::ExportForeachFuncListTy pForEachFuncs) { 5184a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::PassManager BCCPasses; 5194a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5204a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Expand ForEach on CPU path to reduce launch overhead. 5214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines BCCPasses.add(createRSForEachExpandPass(pForEachFuncs)); 5224a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5234a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines BCCPasses.run(*mModule); 5244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5254a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 5264a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} 5274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5284a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesint Compiler::runLTO(llvm::TargetData *TD, 5294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<const char*>& ExportSymbols, 5304a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::CodeGenOpt::Level OptimizationLevel) { 5314a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Note: ExportSymbols is a workaround for getting all exported variable, 5324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // function, and kernel names. 5334a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // We should refine it soon. 5344a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5354a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // TODO(logan): Remove this after we have finished the 5364a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // bccMarkExternalSymbol API. 5374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // root(), init(), and .rs.dtor() are born to be exported 5394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back("root"); 5404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back("init"); 5414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines ExportSymbols.push_back(".rs.dtor"); 5424a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // User-defined exporting symbols 5444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::vector<char const *> const &UserDefinedExternalSymbols = 5454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mpResult->getUserDefinedExternalSymbols(); 5464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::copy(UserDefinedExternalSymbols.begin(), 5484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines UserDefinedExternalSymbols.end(), 5494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::back_inserter(ExportSymbols)); 5504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::PassManager LTOPasses; 5524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5534a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Add TargetData to LTO passes 5544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(TD); 5554a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5564cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien // We now create passes list performing LTO. These are copied from 5574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // (including comments) llvm::createStandardLTOPasses(). 5584a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Only a subset of these LTO passes are enabled in optimization level 0 5594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // as they interfere with interactive debugging. 5604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // FIXME: figure out which passes (if any) makes sense for levels 1 and 2 5614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 5624a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (OptimizationLevel != llvm::CodeGenOpt::None) { 5634a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // Internalize all other symbols not listed in ExportSymbols 5644a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createInternalizePass(ExportSymbols)); 5654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines 566094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Propagate constants at call sites into the functions they call. This 567094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // opens opportunities for globalopt (and inlining) by substituting 568094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // function pointers passed as arguments to direct uses of functions. 5694a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createIPSCCPPass()); 5704cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 571094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Now that we internalized some globals, see if we can hack on them! 5724a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalOptimizerPass()); 5734cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 574094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Linking modules together can lead to duplicated global constants, only 575094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // keep one copy of each constant... 5764a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createConstantMergePass()); 5774cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 578094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove unused arguments from functions... 5794a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createDeadArgEliminationPass()); 5804cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 581094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Reduce the code after globalopt and ipsccp. Both can open up 582094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // significant simplification opportunities, and both can propagate 583094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // functions through function pointers. When this happens, we often have 584094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // to resolve varargs calls, etc, so let instcombine do this. 5854a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createInstructionCombiningPass()); 5864cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 587094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Inline small functions 5884a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createFunctionInliningPass()); 5894cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 590094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead EH info. 5914a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createPruneEHPass()); 5924cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 593094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Internalize the globals again after inlining 5944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalOptimizerPass()); 5954cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 596094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead functions. 5974a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalDCEPass()); 5984cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 599094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // If we didn't decide to inline a function, check to see if we can 600094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // transform it to pass arguments by value instead of by reference. 6014a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createArgumentPromotionPass()); 6024cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 603094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // The IPO passes may leave cruft around. Clean up after them. 6044a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createInstructionCombiningPass()); 6054a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createJumpThreadingPass()); 6064cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 607094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Break up allocas 6084a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createScalarReplAggregatesPass()); 6094cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 610094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Run a few AA driven optimizations here and now, to cleanup the code. 6114a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture. 6124a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis. 6134cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 614094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Hoist loop invariants. 6154a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createLICMPass()); 6164cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 617094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove redundancies. 6184a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGVNPass()); 6194cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 620094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead memcpys. 6214a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createMemCpyOptPass()); 6224cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 623094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Nuke dead stores. 6244a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createDeadStoreEliminationPass()); 6254cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 626094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Cleanup and simplify the code after the scalar optimizations. 6274a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createInstructionCombiningPass()); 6284cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 6294a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createJumpThreadingPass()); 6304cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 631094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Delete basic blocks, which optimization passes may have killed. 6324a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createCFGSimplificationPass()); 6334cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 634094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Now that we have optimized the program, discard unreachable functions. 6354a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalDCEPass()); 636fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 6374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines } else { 6384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createInternalizePass(ExportSymbols)); 6394a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createGlobalOptimizerPass()); 6404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.add(llvm::createConstantMergePass()); 641094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 6424cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 6434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines LTOPasses.run(*mModule); 644da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 6454a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#if ANDROID_ENGINEERING_BUILD 6464a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines if (0 != gDebugDumpDirectory) { 6474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::string errs; 6484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines std::string Filename(gDebugDumpDirectory); 6494a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines Filename += "/post-lto-module.ll"; 6504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines llvm::raw_fd_ostream FS(Filename.c_str(), errs); 6514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines mModule->print(FS, 0); 6524a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines FS.close(); 653094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 6544a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines#endif 655094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 6564a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return 0; 657da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien} 658da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 659da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 6604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hinesvoid *Compiler::getSymbolAddress(char const *name) { 6614a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines return rsloaderGetSymbolAddress(mRSExecutable, name); 662da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien} 663da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 6644a68b1cb89df9507584a51c3444aff99347afb74Stephen HinesCompiler::~Compiler() { 6654a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines rsloaderDisposeExec(mRSExecutable); 666fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 6674a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines // llvm::llvm_shutdown(); 6681f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 6691f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 67090cd3d1ec93c46389c00cd41375608632dd4ceb5Shih-wei Liao 6714a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines} // namespace bcc 672