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