Compiler.cpp revision fef9a1b0b772034b4f0894d1e2b29d1115617be0
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 17c4395235b212be7a626becb0c03020eab4859739Logan#include "Compiler.h" 181f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 19fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Analysis/Passes.h> 20fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/CodeGen/RegAllocRegistry.h> 21fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Module.h> 22fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/PassManager.h> 23fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Support/TargetRegistry.h> 24fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Support/raw_ostream.h> 25fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Target/TargetData.h> 26fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Target/TargetMachine.h> 27fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Transforms/IPO.h> 28fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include <llvm/Transforms/Scalar.h> 29fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 30fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include "CompilerConfig.h" 314dcd6798f3db374a056ea6acc6b425f544c5207cLogan#include "DebugHelper.h" 32fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include "OutputFile.h" 33fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include "Script.h" 34fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang#include "Source.h" 35fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 36fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changusing namespace bcc; 37fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 38fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changconst char *Compiler::GetErrorString(enum ErrorCode pErrCode) { 39fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang static const char *ErrorString[] = { 40fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kSuccess */ 41fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Successfully compiled.", 42fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kInvalidConfigNoTarget */ 43fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Invalid compiler config supplied (getTarget() returns NULL.) " 44fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "(missing call to CompilerConfig::initialize()?)", 45fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrCreateTargetMachine */ 46fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to create llvm::TargetMachine.", 47fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrSwitchTargetMachine */ 48fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to switch llvm::TargetMachine.", 49fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrNoTargetMachine */ 50fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to compile the script since there's no available TargetMachine." 51fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang " (missing call to Compiler::config()?)", 52fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrTargetDataNoMemory */ 53fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Out of memory when create TargetData during compilation.", 54fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrMaterialization */ 55fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to materialize the module.", 56fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrInvalidOutputFileState */ 57fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Supplied output file was invalid (in the error state.)", 58fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrPrepareOutput */ 59fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to prepare file for output.", 60fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kPrepareCodeGenPass */ 61fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Failed to construct pass list for code-generation.", 62fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 63fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookBeforeAddLTOPasses */ 64fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during beforeAddLTOPasses() in subclass.", 65fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookAfterAddLTOPasses */ 66fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during afterAddLTOPasses() in subclass.", 67fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookBeforeExecuteLTOPasses */ 68fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during beforeExecuteLTOPasses() in subclass.", 69fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookAfterExecuteLTOPasses */ 70fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during afterExecuteLTOPasses() in subclass.", 71fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 72fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookBeforeAddCodeGenPasses */ 73fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during beforeAddCodeGenPasses() in subclass.", 74fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookAfterAddCodeGenPasses */ 75fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during afterAddCodeGenPasses() in subclass.", 76fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookBeforeExecuteCodeGenPasses */ 77fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during beforeExecuteCodeGenPasses() in subclass.", 78fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kErrHookAfterExecuteCodeGenPasses */ 79fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "Error occurred during afterExecuteCodeGenPasses() in subclass.", 80fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 81fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* kMaxErrorCode */ 82fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang "(Unknown error code)" 83fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang }; 84fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 85fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (pErrCode > kMaxErrorCode) { 86fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pErrCode = kMaxErrorCode; 87c0554e25638bec2462daf1a66ed0270a60aec8eaAndrew Hsieh } 8851001b86751c1ca36307eddc44a65336079fb698Joseph Wen 89fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return ErrorString[ static_cast<size_t>(pErrCode) ]; 901f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 911f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 92fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang//===----------------------------------------------------------------------===// 93fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang// Instance Methods 94fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang//===----------------------------------------------------------------------===// 95fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr ChangCompiler::Compiler() : mTarget(NULL), mEnableLTO(true) { 96fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return; 971f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 981f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 99fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr ChangCompiler::Compiler(const CompilerConfig &pConfig) : mTarget(NULL), 100fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang mEnableLTO(true) { 101fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang const std::string &triple = pConfig.getTriple(); 102fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 103fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang enum ErrorCode err = config(pConfig); 104fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (err != kSuccess) { 105fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang ALOGE("%s (%s, features: %s)", GetErrorString(err), 106fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang triple.c_str(), pConfig.getFeatureString().c_str()); 107fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return; 108fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 1091f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 1101f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan return; 1111f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 1121f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 113fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changenum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) { 114fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (pConfig.getTarget() == NULL) { 115fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kInvalidConfigNoTarget; 1161f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan } 1171f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 118fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::TargetMachine *new_target = 119fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(), 120fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getCPU(), 121fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getFeatureString(), 122fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getTargetOptions(), 123fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getRelocationModel(), 124fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getCodeModel(), 125fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang pConfig.getOptimizationLevel()); 126fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 127fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (new_target == NULL) { 128fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return ((mTarget != NULL) ? kErrSwitchTargetMachine : 129fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang kErrCreateTargetMachine); 130094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 131094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 132fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Replace the old TargetMachine. 133fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang delete mTarget; 134fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang mTarget = new_target; 135094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 136fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Adjust register allocation policy according to the optimization level. 137094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // createFastRegisterAllocator: fast but bad quality 138094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // createLinearScanRegisterAllocator: not so fast but good quality 139fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) { 140fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator); 141fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } else { 142fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator); 143da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien } 144da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 145fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Relax all machine instructions. 146fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang mTarget->setMCRelaxAll(true); 1471f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 148fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kSuccess; 1491f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 1501f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 151fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr ChangCompiler::~Compiler() { 152fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang delete mTarget; 153db169187dea4602e4ad32058762d23d474753fd0Stephen Hines} 1541f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 155fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changenum Compiler::ErrorCode Compiler::runLTO(Script &pScript) { 156fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::TargetData *target_data = NULL; 157cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines 158fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Pass manager for link-time optimization 159fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::PassManager lto_passes; 1607890d437030c1594bc9c9f61fa1e80a57754b078Logan Chien 161fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Prepare TargetData target data from Module 162fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData()); 163fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (target_data == NULL) { 164fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrTargetDataNoMemory; 165fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 1667890d437030c1594bc9c9f61fa1e80a57754b078Logan Chien 167fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Add TargetData to the pass manager. 168fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(target_data); 169094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 170fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "beforeAddLTOPasses" before adding the first pass. 171fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!beforeAddLTOPasses(pScript, lto_passes)) { 172fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookBeforeAddLTOPasses; 173fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 174094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 1754cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien // We now create passes list performing LTO. These are copied from 176fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // (including comments) llvm::PassManagerBuilder::populateLTOPassManager(). 177fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Only a subset of these LTO passes are enabled in optimization level 0 as 178fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // they interfere with interactive debugging. 179fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // 180fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // FIXME: Figure out which passes (if any) makes sense for levels 1 and 2. 181fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang //if ( != llvm::CodeGenOpt::None) { 182fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) { 183fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalOptimizerPass()); 184fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createConstantMergePass()); 185fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } else { 186094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Propagate constants at call sites into the functions they call. This 187094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // opens opportunities for globalopt (and inlining) by substituting 188094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // function pointers passed as arguments to direct uses of functions. 189fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createIPSCCPPass()); 1904cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 191094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Now that we internalized some globals, see if we can hack on them! 192fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalOptimizerPass()); 1934cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 194094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Linking modules together can lead to duplicated global constants, only 195094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // keep one copy of each constant... 196fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createConstantMergePass()); 1974cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 198094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove unused arguments from functions... 199fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createDeadArgEliminationPass()); 2004cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 201094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Reduce the code after globalopt and ipsccp. Both can open up 202094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // significant simplification opportunities, and both can propagate 203094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // functions through function pointers. When this happens, we often have 204094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // to resolve varargs calls, etc, so let instcombine do this. 205fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createInstructionCombiningPass()); 2064cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 207094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Inline small functions 208fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createFunctionInliningPass()); 2094cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 210094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead EH info. 211fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createPruneEHPass()); 2124cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 213094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Internalize the globals again after inlining 214fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalOptimizerPass()); 2154cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 216094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead functions. 217fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalDCEPass()); 2184cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 219094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // If we didn't decide to inline a function, check to see if we can 220094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // transform it to pass arguments by value instead of by reference. 221fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createArgumentPromotionPass()); 2224cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 223094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // The IPO passes may leave cruft around. Clean up after them. 224fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createInstructionCombiningPass()); 225fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createJumpThreadingPass()); 2264cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 227094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Break up allocas 228fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createScalarReplAggregatesPass()); 2294cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 230094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Run a few AA driven optimizations here and now, to cleanup the code. 231fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createFunctionAttrsPass()); // Add nocapture. 232fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalsModRefPass()); // IP alias analysis. 2334cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 234094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Hoist loop invariants. 235fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createLICMPass()); 2364cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 237094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove redundancies. 238fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGVNPass()); 2394cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 240094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Remove dead memcpys. 241fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createMemCpyOptPass()); 2424cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 243094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Nuke dead stores. 244fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createDeadStoreEliminationPass()); 2454cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 246094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Cleanup and simplify the code after the scalar optimizations. 247fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createInstructionCombiningPass()); 2484cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 249fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createJumpThreadingPass()); 2504cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 251094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Delete basic blocks, which optimization passes may have killed. 252fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createCFGSimplificationPass()); 2534cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 254094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea // Now that we have optimized the program, discard unreachable functions. 255fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.add(llvm::createGlobalDCEPass()); 256fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 257094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 258fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "afterAddLTOPasses" after pass manager finished its 259fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // construction. 260fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!afterAddLTOPasses(pScript, lto_passes)) { 261fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookAfterAddLTOPasses; 262fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 263fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 264fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "beforeExecuteLTOPasses" before executing the passes. 265fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!beforeExecuteLTOPasses(pScript, lto_passes)) { 266fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookBeforeExecuteLTOPasses; 267094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 2684cc0033ef37fc28501d2e337c5bd3b072b9edad0Logan Chien 269fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang lto_passes.run(pScript.getSource().getModule()); 270da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 271fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "afterExecuteLTOPasses" before returning. 272fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!afterExecuteLTOPasses(pScript)) { 273fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookAfterExecuteLTOPasses; 274094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea } 275094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea 276fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kSuccess; 277da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien} 278da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 279fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changenum Compiler::ErrorCode Compiler::runCodeGen(Script &pScript, 280fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::raw_ostream &pResult) { 281fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::TargetData *target_data; 282fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::MCContext *mc_context = NULL; 283fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 284fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Create pass manager for MC code generation. 285fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::PassManager codegen_passes; 286fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 287fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Prepare TargetData target data from Module 288fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData()); 289fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (target_data == NULL) { 290fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrTargetDataNoMemory; 291fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 292fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 293fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Add TargetData to the pass manager. 294fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang codegen_passes.add(target_data); 295fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 296fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "beforeAddCodeGenPasses" before adding the first pass. 297fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!beforeAddCodeGenPasses(pScript, codegen_passes)) { 298fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookBeforeAddCodeGenPasses; 299fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 300fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 301fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Add passes to the pass manager to emit machine code through MC layer. 302fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (mTarget->addPassesToEmitMC(codegen_passes, mc_context, pResult, 303fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang /* DisableVerify */false)) { 304fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kPrepareCodeGenPass; 305fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 306fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 307fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "afterAddCodeGenPasses" after pass manager finished its 308fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // construction. 309fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!afterAddCodeGenPasses(pScript, codegen_passes)) { 310fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookAfterAddCodeGenPasses; 311fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 312fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 313fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "beforeExecuteCodeGenPasses" before executing the passes. 314fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!beforeExecuteCodeGenPasses(pScript, codegen_passes)) { 315fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookBeforeExecuteCodeGenPasses; 316fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 317fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 318fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Execute the pass. 319fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang codegen_passes.run(pScript.getSource().getModule()); 320fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 321fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Invokde "afterExecuteCodeGenPasses" before returning. 322fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (!afterExecuteCodeGenPasses(pScript)) { 323fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrHookAfterExecuteCodeGenPasses; 324fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 325da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 326fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kSuccess; 327da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien} 328da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 329fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changenum Compiler::ErrorCode Compiler::compile(Script &pScript, 330fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::raw_ostream &pResult) { 331fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::Module &module = pScript.getSource().getModule(); 332fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang enum ErrorCode err; 333fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 334fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (mTarget == NULL) { 335fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrNoTargetMachine; 336fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 337fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 338fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Materialize the bitcode module. 339fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (module.getMaterializer() != NULL) { 340fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang std::string error; 341fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // A module with non-null materializer means that it is a lazy-load module. 342fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Materialize it now via invoking MaterializeAllPermanently(). This 343fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // function returns false when the materialization is successful. 344fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (module.MaterializeAllPermanently(&error)) { 345fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang ALOGE("Failed to materialize the module `%s'! (%s)", 346fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang module.getModuleIdentifier().c_str(), error.c_str()); 347fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrMaterialization; 348fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 349fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 350da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien 351fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (mEnableLTO && ((err = runLTO(pScript)) != kSuccess)) { 352fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return err; 353fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 354fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 355fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if ((err = runCodeGen(pScript, pResult)) != kSuccess) { 356fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return err; 357fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 358fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 359fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kSuccess; 3601f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan} 3611f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan 362fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Changenum Compiler::ErrorCode Compiler::compile(Script &pScript, 363fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang OutputFile &pResult) { 364fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Check the state of the specified output file. 365fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (pResult.hasError()) { 366fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrInvalidOutputFileState; 367fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 368fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 369fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Open the output file decorated in llvm::raw_ostream. 370fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang llvm::raw_ostream *out = pResult.dup(); 371fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang if (out == NULL) { 372fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return kErrPrepareOutput; 373fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang } 374fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 375fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Delegate the request. 376fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang enum Compiler::ErrorCode err = compile(pScript, *out); 37790cd3d1ec93c46389c00cd41375608632dd4ceb5Shih-wei Liao 378fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang // Close the output before return. 379fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang delete out; 380fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang 381fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang return err; 382fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang} 383