Compiler.cpp revision a2dd52f0710c214e00c1a13e25116e1af5eec77a
1e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes/*
2e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * Copyright 2010-2012, The Android Open Source Project
3e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes *
4e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * you may not use this file except in compliance with the License.
6e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * You may obtain a copy of the License at
7e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes *
8e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes *     http://www.apache.org/licenses/LICENSE-2.0
9e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes *
10e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * Unless required by applicable law or agreed to in writing, software
11e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * See the License for the specific language governing permissions and
14e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes * limitations under the License.
15e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes */
16e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banes#include "Assert.h"
18e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include "Log.h"
19e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include "OutputFile.h"
20d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include "RSTransforms.h"
21e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include "RSUtils.h"
228f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette#include "rsDefines.h"
2330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
24e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include "bcc/Compiler.h"
25d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include "bcc/CompilerConfig.h"
2630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell#include "bcc/Config.h"
2730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell#include "bcc/RSScript.h"
28e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include "bcc/Script.h"
29d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include "bcc/Source.h"
30d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include "bcinfo/MetadataExtractor.h"
31d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes
328f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette#include <llvm/Analysis/Passes.h>
33d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include <llvm/Analysis/TargetTransformInfo.h>
34e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/CodeGen/RegAllocRegistry.h>
35d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include <llvm/IR/LegacyPassManager.h>
36d837ef307ff53290159c0d7c8cf9e3e0dc2fa410Chris Banes#include <llvm/IR/Module.h>
37e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Support/TargetRegistry.h>
38e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Support/raw_ostream.h>
39e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/IR/DataLayout.h>
40e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Target/TargetSubtargetInfo.h>
41e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Target/TargetMachine.h>
42e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Transforms/IPO.h>
43e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Transforms/IPO/PassManagerBuilder.h>
44e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Transforms/Scalar.h>
45e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <llvm/Transforms/Vectorize.h>
46e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
47e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <string>
48e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes#include <set>
49e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
50e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banesusing namespace bcc;
51e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
52e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banesconst char *Compiler::GetErrorString(enum ErrorCode pErrCode) {
53e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  switch (pErrCode) {
54e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kSuccess:
55e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Successfully compiled.";
56e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kInvalidConfigNoTarget:
57e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Invalid compiler config supplied (getTarget() returns nullptr.) "
58e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes           "(missing call to CompilerConfig::initialize()?)";
59e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrCreateTargetMachine:
60e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Failed to create llvm::TargetMachine.";
61e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrSwitchTargetMachine:
62e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return  "Failed to switch llvm::TargetMachine.";
63e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrNoTargetMachine:
64e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Failed to compile the script since there's no available "
65e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes           "TargetMachine. (missing call to Compiler::config()?)";
66e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrMaterialization:
67e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Failed to materialize the module.";
68e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrInvalidOutputFileState:
69e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Supplied output file was invalid (in the error state.)";
70e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrPrepareOutput:
71e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Failed to prepare file for output.";
72e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kPrepareCodeGenPass:
73e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Failed to construct pass list for code-generation.";
74e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrCustomPasses:
75e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Error occurred while adding custom passes.";
76e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrInvalidSource:
77e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Error loading input bitcode";
78e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kIllegalGlobalFunction:
79e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Use of undefined external function";
80e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  case kErrInvalidTargetMachine:
81e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return "Invalid/unexpected llvm::TargetMachine.";
82e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
83e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
84e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // This assert should never be reached as the compiler verifies that the
85e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // above switch coveres all enum values.
86e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  bccAssert(false && "Unknown error code encountered");
87e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  return  "";
88e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes}
89e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
90e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes//===----------------------------------------------------------------------===//
91e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes// Instance Methods
92e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes//===----------------------------------------------------------------------===//
93e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris BanesCompiler::Compiler() : mTarget(nullptr), mEnableOpt(true) {
94e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  return;
95e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes}
96e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
97e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris BanesCompiler::Compiler(const CompilerConfig &pConfig) : mTarget(nullptr),
98e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                    mEnableOpt(true) {
99e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  const std::string &triple = pConfig.getTriple();
100e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
101e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  enum ErrorCode err = config(pConfig);
102e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if (err != kSuccess) {
103e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    ALOGE("%s (%s, features: %s)", GetErrorString(err),
104e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes          triple.c_str(), pConfig.getFeatureString().c_str());
105e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return;
106e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
107e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
108e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  return;
109e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes}
110e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
111e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banesenum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) {
112e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if (pConfig.getTarget() == nullptr) {
113e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return kInvalidConfigNoTarget;
114e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
115e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
116e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  llvm::TargetMachine *new_target =
117e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes      (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(),
118e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getCPU(),
119e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getFeatureString(),
120e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getTargetOptions(),
121e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getRelocationModel(),
122e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getCodeModel(),
123e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                                 pConfig.getOptimizationLevel());
124e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
125e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if (new_target == nullptr) {
126e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    return ((mTarget != nullptr) ? kErrSwitchTargetMachine :
127e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                   kErrCreateTargetMachine);
128e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
129e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
130e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // Replace the old TargetMachine.
131e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  delete mTarget;
132e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  mTarget = new_target;
133e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
134e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // Adjust register allocation policy according to the optimization level.
135e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  //  createFastRegisterAllocator: fast but bad quality
136e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  //  createLinearScanRegisterAllocator: not so fast but good quality
137e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) {
138e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator);
139e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  } else {
140e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator);
141e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
142e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
143e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  return kSuccess;
144e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes}
145e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
146e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris BanesCompiler::~Compiler() {
147e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  delete mTarget;
148e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes}
149e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
150e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
151e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes// This function has complete responsibility for creating and executing the
152e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes// exact list of compiler passes.
153e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banesenum Compiler::ErrorCode Compiler::runPasses(Script &pScript,
154e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes                                             llvm::raw_pwrite_stream &pResult) {
155e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // Pass manager for link-time optimization
156e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  llvm::legacy::PassManager transformPasses;
157e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
158e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // Empty MCContext.
159e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  llvm::MCContext *mc_context = nullptr;
160e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
161e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  transformPasses.add(
162e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes      createTargetTransformInfoWrapperPass(mTarget->getTargetIRAnalysis()));
163e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
164e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  // Add some initial custom passes.
165e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  addInvokeHelperPass(transformPasses);
166e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  addExpandKernelPass(transformPasses);
167e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  addDebugInfoPass(pScript, transformPasses);
168e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  addInvariantPass(transformPasses);
169e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if (mTarget->getOptLevel() != llvm::CodeGenOpt::None) {
170e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    if (!addInternalizeSymbolsPass(pScript, transformPasses))
171e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes      return kErrCustomPasses;
172e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  }
173e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  addGlobalInfoPass(pScript, transformPasses);
174e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes
175e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes  if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
176e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    transformPasses.add(llvm::createGlobalOptimizerPass());
177e73e46ef5b69ecdf18aa1947e0a1b3e4ec5d1ee7Chris Banes    transformPasses.add(llvm::createConstantMergePass());
178
179  } else {
180    // FIXME: Figure out which passes should be executed.
181    llvm::PassManagerBuilder Builder;
182    Builder.Inliner = llvm::createFunctionInliningPass();
183    Builder.populateLTOPassManager(transformPasses);
184
185    /* FIXME: Reenable autovectorization after rebase.
186       bug 19324423
187    // Add vectorization passes after LTO passes are in
188    // additional flag: -unroll-runtime
189    transformPasses.add(llvm::createLoopUnrollPass(-1, 16, 0, 1));
190    // Need to pass appropriate flags here: -scalarize-load-store
191    transformPasses.add(llvm::createScalarizerPass());
192    transformPasses.add(llvm::createCFGSimplificationPass());
193    transformPasses.add(llvm::createScopedNoAliasAAPass());
194    transformPasses.add(llvm::createScalarEvolutionAliasAnalysisPass());
195    // additional flags: -slp-vectorize-hor -slp-vectorize-hor-store (unnecessary?)
196    transformPasses.add(llvm::createSLPVectorizerPass());
197    transformPasses.add(llvm::createDeadCodeEliminationPass());
198    transformPasses.add(llvm::createInstructionCombiningPass());
199    */
200  }
201
202  // These passes have to come after LTO, since we don't want to examine
203  // functions that are never actually called.
204  if (llvm::Triple(getTargetMachine().getTargetTriple()).getArch() == llvm::Triple::x86_64)
205    transformPasses.add(createRSX86_64CallConvPass());  // Add pass to correct calling convention for X86-64.
206  transformPasses.add(createRSIsThreadablePass());      // Add pass to mark script as threadable.
207
208  // RSEmbedInfoPass needs to come after we have scanned for non-threadable
209  // functions.
210  // Script passed to RSCompiler must be a RSScript.
211  RSScript &script = static_cast<RSScript &>(pScript);
212  if (script.getEmbedInfo())
213    transformPasses.add(createRSEmbedInfoPass());
214
215  // Execute the passes.
216  transformPasses.run(pScript.getSource().getModule());
217
218  // Run backend separately to avoid interference between debug metadata
219  // generation and backend initialization.
220  llvm::legacy::PassManager codeGenPasses;
221
222  // Add passes to the pass manager to emit machine code through MC layer.
223  if (mTarget->addPassesToEmitMC(codeGenPasses, mc_context, pResult,
224                                 /* DisableVerify */false)) {
225    return kPrepareCodeGenPass;
226  }
227
228  // Execute the passes.
229  codeGenPasses.run(pScript.getSource().getModule());
230
231  return kSuccess;
232}
233
234enum Compiler::ErrorCode Compiler::compile(Script &pScript,
235                                           llvm::raw_pwrite_stream &pResult,
236                                           llvm::raw_ostream *IRStream) {
237  llvm::Module &module = pScript.getSource().getModule();
238  enum ErrorCode err;
239
240  if (mTarget == nullptr) {
241    return kErrNoTargetMachine;
242  }
243
244  const std::string &triple = module.getTargetTriple();
245  const llvm::DataLayout dl = getTargetMachine().createDataLayout();
246  unsigned int pointerSize = dl.getPointerSizeInBits();
247  if (triple == "armv7-none-linux-gnueabi") {
248    if (pointerSize != 32) {
249      return kErrInvalidSource;
250    }
251  } else if (triple == "aarch64-none-linux-gnueabi") {
252    if (pointerSize != 64) {
253      return kErrInvalidSource;
254    }
255  } else {
256    return kErrInvalidSource;
257  }
258
259  if (getTargetMachine().getTargetTriple().getArch() == llvm::Triple::x86) {
260    // Detect and fail if TargetMachine datalayout is different than what we
261    // expect.  This is to detect changes in default target layout for x86 and
262    // update X86_CUSTOM_DL_STRING in include/bcc/Config/Config.h appropriately.
263    if (dl.getStringRepresentation().compare(X86_DEFAULT_DL_STRING) != 0) {
264      return kErrInvalidTargetMachine;
265    }
266  }
267
268  // Sanitize module's target information.
269  module.setTargetTriple(getTargetMachine().getTargetTriple().str());
270  module.setDataLayout(getTargetMachine().createDataLayout());
271
272  // Materialize the bitcode module.
273  if (module.getMaterializer() != nullptr) {
274    // A module with non-null materializer means that it is a lazy-load module.
275    // Materialize it now.  This function returns false when the materialization
276    // is successful.
277    std::error_code ec = module.materializeAll();
278    if (ec) {
279      ALOGE("Failed to materialize the module `%s'! (%s)",
280            module.getModuleIdentifier().c_str(), ec.message().c_str());
281      return kErrMaterialization;
282    }
283  }
284
285  if ((err = runPasses(pScript, pResult)) != kSuccess) {
286    return err;
287  }
288
289  if (IRStream) {
290    *IRStream << module;
291  }
292
293  return kSuccess;
294}
295
296enum Compiler::ErrorCode Compiler::compile(Script &pScript,
297                                           OutputFile &pResult,
298                                           llvm::raw_ostream *IRStream) {
299  // Check the state of the specified output file.
300  if (pResult.hasError()) {
301    return kErrInvalidOutputFileState;
302  }
303
304  // Open the output file decorated in llvm::raw_ostream.
305  llvm::raw_pwrite_stream *out = pResult.dup();
306  if (out == nullptr) {
307    return kErrPrepareOutput;
308  }
309
310  // Delegate the request.
311  enum Compiler::ErrorCode err = compile(pScript, *out, IRStream);
312
313  // Close the output before return.
314  delete out;
315
316  return err;
317}
318
319bool Compiler::addInternalizeSymbolsPass(Script &pScript, llvm::legacy::PassManager &pPM) {
320  // Add a pass to internalize the symbols that don't need to have global
321  // visibility.
322  RSScript &script = static_cast<RSScript &>(pScript);
323  llvm::Module &module = script.getSource().getModule();
324  bcinfo::MetadataExtractor me(&module);
325  if (!me.extract()) {
326    bccAssert(false && "Could not extract metadata for module!");
327    return false;
328  }
329
330  // Set of symbols that should not be internalized.
331  std::set<std::string> export_symbols;
332
333  const char *sf[] = {
334    kRoot,               // Graphics drawing function or compute kernel.
335    kInit,               // Initialization routine called implicitly on startup.
336    kRsDtor,             // Static global destructor for a script instance.
337    kRsInfo,             // Variable containing string of RS metadata info.
338    kRsGlobalEntries,    // Optional number of global variables.
339    kRsGlobalNames,      // Optional global variable name info.
340    kRsGlobalAddresses,  // Optional global variable address info.
341    kRsGlobalSizes,      // Optional global variable size info.
342    kRsGlobalProperties, // Optional global variable properties.
343    nullptr              // Must be nullptr-terminated.
344  };
345  const char **special_functions = sf;
346  // Special RS functions should always be global symbols.
347  while (*special_functions != nullptr) {
348    export_symbols.insert(*special_functions);
349    special_functions++;
350  }
351
352  // Visibility of symbols appeared in rs_export_var and rs_export_func should
353  // also be preserved.
354  size_t exportVarCount = me.getExportVarCount();
355  size_t exportFuncCount = me.getExportFuncCount();
356  size_t exportForEachCount = me.getExportForEachSignatureCount();
357  size_t exportReduceCount = me.getExportReduceCount();
358  const char **exportVarNameList = me.getExportVarNameList();
359  const char **exportFuncNameList = me.getExportFuncNameList();
360  const char **exportForEachNameList = me.getExportForEachNameList();
361  const bcinfo::MetadataExtractor::Reduce *exportReduceList = me.getExportReduceList();
362  size_t i;
363
364  for (i = 0; i < exportVarCount; ++i) {
365    export_symbols.insert(exportVarNameList[i]);
366  }
367
368  for (i = 0; i < exportFuncCount; ++i) {
369    export_symbols.insert(exportFuncNameList[i]);
370  }
371
372  // Expanded foreach functions should not be internalized; nor should
373  // general reduction initializer, combiner, and outconverter
374  // functions. keep_funcs keeps the names of these functions around
375  // until createInternalizePass() is finished making its own copy of
376  // the visible symbols.
377  std::vector<std::string> keep_funcs;
378  keep_funcs.reserve(exportForEachCount + exportReduceCount*4);
379
380  for (i = 0; i < exportForEachCount; ++i) {
381    keep_funcs.push_back(std::string(exportForEachNameList[i]) + ".expand");
382  }
383  auto keepFuncsPushBackIfPresent = [&keep_funcs](const char *Name) {
384    if (Name) keep_funcs.push_back(Name);
385  };
386  for (i = 0; i < exportReduceCount; ++i) {
387    keep_funcs.push_back(std::string(exportReduceList[i].mAccumulatorName) + ".expand");
388    keepFuncsPushBackIfPresent(exportReduceList[i].mInitializerName);
389    if (exportReduceList[i].mCombinerName != nullptr) {
390      keep_funcs.push_back(exportReduceList[i].mCombinerName);
391    } else {
392      keep_funcs.push_back(nameReduceCombinerFromAccumulator(exportReduceList[i].mAccumulatorName));
393    }
394    keepFuncsPushBackIfPresent(exportReduceList[i].mOutConverterName);
395  }
396
397  for (auto &symbol_name : keep_funcs) {
398    export_symbols.insert(symbol_name);
399  }
400
401  auto IsExportedSymbol = [=](const llvm::GlobalValue &GV) {
402    return export_symbols.count(GV.getName()) > 0;
403  };
404
405  pPM.add(llvm::createInternalizePass(IsExportedSymbol));
406
407  return true;
408}
409
410void Compiler::addInvokeHelperPass(llvm::legacy::PassManager &pPM) {
411  llvm::Triple arch(getTargetMachine().getTargetTriple());
412  if (arch.isArch64Bit()) {
413    pPM.add(createRSInvokeHelperPass());
414  }
415}
416
417void Compiler::addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
418  if (pScript.getSource().getDebugInfoEnabled())
419    pPM.add(createRSAddDebugInfoPass());
420}
421
422void Compiler::addExpandKernelPass(llvm::legacy::PassManager &pPM) {
423  // Expand ForEach and reduce on CPU path to reduce launch overhead.
424  bool pEnableStepOpt = true;
425  pPM.add(createRSKernelExpandPass(pEnableStepOpt));
426}
427
428void Compiler::addGlobalInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
429  // Add additional information about RS global variables inside the Module.
430  RSScript &script = static_cast<RSScript &>(pScript);
431  if (script.getEmbedGlobalInfo()) {
432    pPM.add(createRSGlobalInfoPass(script.getEmbedGlobalInfoSkipConstant()));
433  }
434}
435
436void Compiler::addInvariantPass(llvm::legacy::PassManager &pPM) {
437  // Mark Loads from RsExpandKernelDriverInfo as "load.invariant".
438  // Should run after ExpandForEach and before inlining.
439  pPM.add(createRSInvariantPass());
440}
441
442enum Compiler::ErrorCode Compiler::screenGlobalFunctions(Script &pScript) {
443  llvm::Module &module = pScript.getSource().getModule();
444
445  // Materialize the bitcode module in case this is a lazy-load module.  Do not
446  // clear the materializer by calling materializeAllPermanently since the
447  // runtime library has not been merged into the module yet.
448  if (module.getMaterializer() != nullptr) {
449    std::error_code ec = module.materializeAll();
450    if (ec) {
451      ALOGE("Failed to materialize module `%s' when screening globals! (%s)",
452            module.getModuleIdentifier().c_str(), ec.message().c_str());
453      return kErrMaterialization;
454    }
455  }
456
457  // Add pass to check for illegal function calls.
458  llvm::legacy::PassManager pPM;
459  pPM.add(createRSScreenFunctionsPass());
460  pPM.run(module);
461
462  return kSuccess;
463
464}
465
466void Compiler::translateGEPs(Script &pScript) {
467  llvm::legacy::PassManager pPM;
468  pPM.add(createRSX86TranslateGEPPass());
469
470  // Materialization done in screenGlobalFunctions above.
471  pPM.run(pScript.getSource().getModule());
472}
473