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>
21b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h>
22ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/PassManager.h>
23ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Support/TargetRegistry.h>
24ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Support/raw_ostream.h>
25b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/DataLayout.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()?)",
52b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines    /* kErrDataLayoutNoMemory */
53b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines    "Out of memory when create DataLayout 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) {
156b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  llvm::DataLayout *data_layout = NULL;
1574a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
158ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Pass manager for link-time optimization
159ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  llvm::PassManager lto_passes;
1604a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
161b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  // Prepare DataLayout target data from Module
162b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  data_layout = new (std::nothrow) llvm::DataLayout(*mTarget->getDataLayout());
163b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  if (data_layout == NULL) {
164b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines    return kErrDataLayoutNoMemory;
165ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
1664a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
167b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  // Add DataLayout to the pass manager.
168b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  lto_passes.add(data_layout);
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) {
281b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  llvm::DataLayout *data_layout;
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
287b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  // Prepare DataLayout target data from Module
288b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  data_layout = new (std::nothrow) llvm::DataLayout(*mTarget->getDataLayout());
289b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  if (data_layout == NULL) {
290b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines    return kErrDataLayoutNoMemory;
291ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
292ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
293b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  // Add DataLayout to the pass manager.
294b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines  codegen_passes.add(data_layout);
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