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