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>
201bd9f627fa0affb457507e86b0b6684c695fe726Stephen Hines#include <llvm/Analysis/TargetTransformInfo.h>
21ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/CodeGen/RegAllocRegistry.h>
221bd9f627fa0affb457507e86b0b6684c695fe726Stephen Hines#include <llvm/IR/LegacyPassManager.h>
23b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h>
24ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Support/TargetRegistry.h>
25ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Support/raw_ostream.h>
26b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/DataLayout.h>
27579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines#include <llvm/Target/TargetSubtargetInfo.h>
28ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Target/TargetMachine.h>
29ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Transforms/IPO.h>
302f6103bb820139d19f709e687f5bf4f86226057eTobias Grosser#include <llvm/Transforms/IPO/PassManagerBuilder.h>
31ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang#include <llvm/Transforms/Scalar.h>
3250f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray#include <llvm/Transforms/Vectorize.h>
33ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
34b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes#include "bcc/Assert.h"
359e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include "bcc/Config/Config.h"
36b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes#include "bcc/Renderscript/RSScript.h"
37b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes#include "bcc/Renderscript/RSTransforms.h"
3857fd9f882f3359be4201c42b02aebf785d311df2David Gross#include "bcc/Renderscript/RSUtils.h"
39c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Script.h"
40c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Source.h"
41c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Support/CompilerConfig.h"
42ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h"
43c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Support/OutputFile.h"
44b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes#include "bcinfo/MetadataExtractor.h"
45fb81ec1a875d13d9750006313b9123903336101dStephen Hines#include "rsDefines.h"
46ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
4710ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines#include <string>
4810ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines
49ade92778b99382413ff9c556c724dd3f447e5dfbZonr Changusing namespace bcc;
50ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
51ade92778b99382413ff9c556c724dd3f447e5dfbZonr Changconst char *Compiler::GetErrorString(enum ErrorCode pErrCode) {
525b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  switch (pErrCode) {
535b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kSuccess:
545b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Successfully compiled.";
555b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kInvalidConfigNoTarget:
56900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes    return "Invalid compiler config supplied (getTarget() returns nullptr.) "
575b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser           "(missing call to CompilerConfig::initialize()?)";
585b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrCreateTargetMachine:
595b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Failed to create llvm::TargetMachine.";
605b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrSwitchTargetMachine:
615b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return  "Failed to switch llvm::TargetMachine.";
625b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrNoTargetMachine:
635b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Failed to compile the script since there's no available "
645b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser           "TargetMachine. (missing call to Compiler::config()?)";
655b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrMaterialization:
665b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Failed to materialize the module.";
675b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrInvalidOutputFileState:
685b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Supplied output file was invalid (in the error state.)";
695b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrPrepareOutput:
705b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Failed to prepare file for output.";
715b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kPrepareCodeGenPass:
725b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Failed to construct pass list for code-generation.";
73b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  case kErrCustomPasses:
74b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    return "Error occurred while adding custom passes.";
755b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  case kErrInvalidSource:
765b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser    return "Error loading input bitcode";
771e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar  case kIllegalGlobalFunction:
781e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar    return "Use of undefined external function";
799e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  case kErrInvalidTargetMachine:
809e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    return "Invalid/unexpected llvm::TargetMachine.";
814a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines  }
824a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
835b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  // This assert should never be reached as the compiler verifies that the
845b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  // above switch coveres all enum values.
85c2ca742d7d0197c52e49467862844463fb42280fDavid Gross  bccAssert(false && "Unknown error code encountered");
865b7f52aff2030d520ee2ac6d3ac7d917f38d550cTobias Grosser  return  "";
874a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines}
884a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
89ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang//===----------------------------------------------------------------------===//
90ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang// Instance Methods
91ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang//===----------------------------------------------------------------------===//
92b4447cd2b14f53efd9102d28da48000be7b2d4fdChris WailesCompiler::Compiler() : mTarget(nullptr), mEnableOpt(true) {
93ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  return;
944a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines}
954a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
96900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris WailesCompiler::Compiler(const CompilerConfig &pConfig) : mTarget(nullptr),
97b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes                                                    mEnableOpt(true) {
98ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  const std::string &triple = pConfig.getTriple();
99ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
100ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  enum ErrorCode err = config(pConfig);
101ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  if (err != kSuccess) {
102ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    ALOGE("%s (%s, features: %s)", GetErrorString(err),
103ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang          triple.c_str(), pConfig.getFeatureString().c_str());
104ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return;
105ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
1064a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
1071f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan  return;
1081f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan}
1091f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan
110ade92778b99382413ff9c556c724dd3f447e5dfbZonr Changenum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) {
111900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes  if (pConfig.getTarget() == nullptr) {
112ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return kInvalidConfigNoTarget;
1131f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan  }
1144a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
115ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  llvm::TargetMachine *new_target =
116ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang      (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(),
117ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getCPU(),
118ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getFeatureString(),
119ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getTargetOptions(),
120ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getRelocationModel(),
121ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getCodeModel(),
122ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                                 pConfig.getOptimizationLevel());
123ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
124900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes  if (new_target == nullptr) {
125900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes    return ((mTarget != nullptr) ? kErrSwitchTargetMachine :
126b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes                                   kErrCreateTargetMachine);
127094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
128094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
129ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Replace the old TargetMachine.
130ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  delete mTarget;
131ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  mTarget = new_target;
132094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
133ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Adjust register allocation policy according to the optimization level.
134094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  //  createFastRegisterAllocator: fast but bad quality
135094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  //  createLinearScanRegisterAllocator: not so fast but good quality
136ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) {
137ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator);
138ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  } else {
139ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator);
1404a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines  }
1414a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
142ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  return kSuccess;
1434a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines}
1444a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
145ade92778b99382413ff9c556c724dd3f447e5dfbZonr ChangCompiler::~Compiler() {
146ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  delete mTarget;
1474a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines}
1484a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
1491e0557ae75ae780352845bd2ba0f4babdc5ae4e6Pirama Arumuga Nainar
1505aefc98db2dc14a703ce3d4f134565b834686552David Gross// This function has complete responsibility for creating and executing the
1515aefc98db2dc14a703ce3d4f134565b834686552David Gross// exact list of compiler passes.
152b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailesenum Compiler::ErrorCode Compiler::runPasses(Script &pScript,
15398137cca7eebca946b869b010fef2821c9bf4971Pirama Arumuga Nainar                                             llvm::raw_pwrite_stream &pResult) {
154ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Pass manager for link-time optimization
1551e321862daea867b44700360c4827bcb7b97968aDean De Leo  llvm::legacy::PassManager transformPasses;
156b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
157b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // Empty MCContext.
158b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  llvm::MCContext *mc_context = nullptr;
1594a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
1601e321862daea867b44700360c4827bcb7b97968aDean De Leo  transformPasses.add(
1611e321862daea867b44700360c4827bcb7b97968aDean De Leo      createTargetTransformInfoWrapperPass(mTarget->getTargetIRAnalysis()));
162bb73b74a9f6ad26c2ab30557bfe6916a44ed75f6Tim Murray
1635aefc98db2dc14a703ce3d4f134565b834686552David Gross  // Add some initial custom passes.
1641e321862daea867b44700360c4827bcb7b97968aDean De Leo  addInvokeHelperPass(transformPasses);
1651e321862daea867b44700360c4827bcb7b97968aDean De Leo  addExpandKernelPass(transformPasses);
16609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  addDebugInfoPass(pScript, transformPasses);
1671e321862daea867b44700360c4827bcb7b97968aDean De Leo  addInvariantPass(transformPasses);
1687a9a96766a6636218b516d61fbe47a99dea8afc4Dean De Leo  if (mTarget->getOptLevel() != llvm::CodeGenOpt::None) {
1697a9a96766a6636218b516d61fbe47a99dea8afc4Dean De Leo    if (!addInternalizeSymbolsPass(pScript, transformPasses))
1707a9a96766a6636218b516d61fbe47a99dea8afc4Dean De Leo      return kErrCustomPasses;
1717a9a96766a6636218b516d61fbe47a99dea8afc4Dean De Leo  }
1721e321862daea867b44700360c4827bcb7b97968aDean De Leo  addGlobalInfoPass(pScript, transformPasses);
1734a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
174ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
1751e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createGlobalOptimizerPass());
1761e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createConstantMergePass());
177b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
178ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  } else {
1792f6103bb820139d19f709e687f5bf4f86226057eTobias Grosser    // FIXME: Figure out which passes should be executed.
1802f6103bb820139d19f709e687f5bf4f86226057eTobias Grosser    llvm::PassManagerBuilder Builder;
181579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines    Builder.Inliner = llvm::createFunctionInliningPass();
1821e321862daea867b44700360c4827bcb7b97968aDean De Leo    Builder.populateLTOPassManager(transformPasses);
18350f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray
1847f59b5f76c7149b42ff6d4910c6f6165b3358e72Tim Murray    /* FIXME: Reenable autovectorization after rebase.
1857f59b5f76c7149b42ff6d4910c6f6165b3358e72Tim Murray       bug 19324423
18650f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray    // Add vectorization passes after LTO passes are in
18750f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray    // additional flag: -unroll-runtime
1881e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createLoopUnrollPass(-1, 16, 0, 1));
18950f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray    // Need to pass appropriate flags here: -scalarize-load-store
1901e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createScalarizerPass());
1911e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createCFGSimplificationPass());
1921e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createScopedNoAliasAAPass());
1931e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createScalarEvolutionAliasAnalysisPass());
19450f5eb4b27ce6dd2a02cf389ac2acfa95c6939f1Tim Murray    // additional flags: -slp-vectorize-hor -slp-vectorize-hor-store (unnecessary?)
1951e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createSLPVectorizerPass());
1961e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createDeadCodeEliminationPass());
1971e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(llvm::createInstructionCombiningPass());
1987f59b5f76c7149b42ff6d4910c6f6165b3358e72Tim Murray    */
199ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
200ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
2018c24f8d1d75b619130e8bfce204ed9695362d4a1Pirama Arumuga Nainar  // These passes have to come after LTO, since we don't want to examine
2028c24f8d1d75b619130e8bfce204ed9695362d4a1Pirama Arumuga Nainar  // functions that are never actually called.
2035aefc98db2dc14a703ce3d4f134565b834686552David Gross  if (llvm::Triple(getTargetMachine().getTargetTriple()).getArch() == llvm::Triple::x86_64)
2041e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(createRSX86_64CallConvPass());  // Add pass to correct calling convention for X86-64.
2051e321862daea867b44700360c4827bcb7b97968aDean De Leo  transformPasses.add(createRSIsThreadablePass());      // Add pass to mark script as threadable.
2069fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
2079fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  // RSEmbedInfoPass needs to come after we have scanned for non-threadable
2089fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  // functions.
2099fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  // Script passed to RSCompiler must be a RSScript.
2109fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  RSScript &script = static_cast<RSScript &>(pScript);
2119fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  if (script.getEmbedInfo())
2121e321862daea867b44700360c4827bcb7b97968aDean De Leo    transformPasses.add(createRSEmbedInfoPass());
2131e321862daea867b44700360c4827bcb7b97968aDean De Leo
2141e321862daea867b44700360c4827bcb7b97968aDean De Leo  // Execute the passes.
2151e321862daea867b44700360c4827bcb7b97968aDean De Leo  transformPasses.run(pScript.getSource().getModule());
2161e321862daea867b44700360c4827bcb7b97968aDean De Leo
2171e321862daea867b44700360c4827bcb7b97968aDean De Leo  // Run backend separately to avoid interference between debug metadata
2181e321862daea867b44700360c4827bcb7b97968aDean De Leo  // generation and backend initialization.
2191e321862daea867b44700360c4827bcb7b97968aDean De Leo  llvm::legacy::PassManager codeGenPasses;
2205db508c73e6177eb306bac4725616b7c001587c4Stephen Hines
221ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Add passes to the pass manager to emit machine code through MC layer.
2221e321862daea867b44700360c4827bcb7b97968aDean De Leo  if (mTarget->addPassesToEmitMC(codeGenPasses, mc_context, pResult,
223ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang                                 /* DisableVerify */false)) {
224ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return kPrepareCodeGenPass;
225ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
226ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
227b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // Execute the passes.
2281e321862daea867b44700360c4827bcb7b97968aDean De Leo  codeGenPasses.run(pScript.getSource().getModule());
229ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
230ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  return kSuccess;
231da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien}
232da5e0c369ad20bf70556c7e7cf86807cf171730dLogan Chien
233ade92778b99382413ff9c556c724dd3f447e5dfbZonr Changenum Compiler::ErrorCode Compiler::compile(Script &pScript,
23498137cca7eebca946b869b010fef2821c9bf4971Pirama Arumuga Nainar                                           llvm::raw_pwrite_stream &pResult,
23527fb7edfd3f53f52fba6ee81267c02f7896198a3Tobias Grosser                                           llvm::raw_ostream *IRStream) {
236ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  llvm::Module &module = pScript.getSource().getModule();
237ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  enum ErrorCode err;
238ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
239900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes  if (mTarget == nullptr) {
240ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return kErrNoTargetMachine;
241ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
242ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
24310ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines  const std::string &triple = module.getTargetTriple();
2448e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar  const llvm::DataLayout dl = getTargetMachine().createDataLayout();
2458e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar  unsigned int pointerSize = dl.getPointerSizeInBits();
24610ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines  if (triple == "armv7-none-linux-gnueabi") {
24710ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines    if (pointerSize != 32) {
24810ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines      return kErrInvalidSource;
24910ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines    }
25010ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines  } else if (triple == "aarch64-none-linux-gnueabi") {
25110ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines    if (pointerSize != 64) {
25210ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines      return kErrInvalidSource;
25310ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines    }
25410ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines  } else {
25510ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines    return kErrInvalidSource;
25610ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines  }
25710ee6af612d585301c6f2b2f0f04e9bc80b338bbStephen Hines
2589e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  if (getTargetMachine().getTargetTriple().getArch() == llvm::Triple::x86) {
2599e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    // Detect and fail if TargetMachine datalayout is different than what we
2609e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    // expect.  This is to detect changes in default target layout for x86 and
2619e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    // update X86_CUSTOM_DL_STRING in include/bcc/Config/Config.h appropriately.
2629e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    if (dl.getStringRepresentation().compare(X86_DEFAULT_DL_STRING) != 0) {
2639e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar      return kErrInvalidTargetMachine;
2649e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar    }
2659e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  }
2669e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar
267cf8b2d0d2fcd7acf9769b3e1f26ac6e3a0a9b6e7David Gross  // Sanitize module's target information.
2688e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar  module.setTargetTriple(getTargetMachine().getTargetTriple().str());
2698e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar  module.setDataLayout(getTargetMachine().createDataLayout());
270cf8b2d0d2fcd7acf9769b3e1f26ac6e3a0a9b6e7David Gross
271ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Materialize the bitcode module.
272900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes  if (module.getMaterializer() != nullptr) {
273ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    // A module with non-null materializer means that it is a lazy-load module.
2748e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar    // Materialize it now.  This function returns false when the materialization
2758e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar    // is successful.
2768e9089377848628813a697b972773e969b942c3bPirama Arumuga Nainar    std::error_code ec = module.materializeAll();
277c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray    if (ec) {
278ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang      ALOGE("Failed to materialize the module `%s'! (%s)",
279c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray            module.getModuleIdentifier().c_str(), ec.message().c_str());
280ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang      return kErrMaterialization;
281ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    }
282ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
283fef9a1b0b772034b4f0894d1e2b29d1115617be0Zonr Chang
284b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  if ((err = runPasses(pScript, pResult)) != kSuccess) {
285ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return err;
286ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
287ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
288b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  if (IRStream) {
28927fb7edfd3f53f52fba6ee81267c02f7896198a3Tobias Grosser    *IRStream << module;
290ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
291ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
292ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  return kSuccess;
2931f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan}
2941f028c027b1df7fde0cd1a1eef9730856e8e5ae9Logan
295ade92778b99382413ff9c556c724dd3f447e5dfbZonr Changenum Compiler::ErrorCode Compiler::compile(Script &pScript,
29627fb7edfd3f53f52fba6ee81267c02f7896198a3Tobias Grosser                                           OutputFile &pResult,
29727fb7edfd3f53f52fba6ee81267c02f7896198a3Tobias Grosser                                           llvm::raw_ostream *IRStream) {
298ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Check the state of the specified output file.
299ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  if (pResult.hasError()) {
300ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return kErrInvalidOutputFileState;
301ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
302ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
303ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Open the output file decorated in llvm::raw_ostream.
30498137cca7eebca946b869b010fef2821c9bf4971Pirama Arumuga Nainar  llvm::raw_pwrite_stream *out = pResult.dup();
305900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes  if (out == nullptr) {
306ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang    return kErrPrepareOutput;
307ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  }
308ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
309ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Delegate the request.
31027fb7edfd3f53f52fba6ee81267c02f7896198a3Tobias Grosser  enum Compiler::ErrorCode err = compile(pScript, *out, IRStream);
31190cd3d1ec93c46389c00cd41375608632dd4ceb5Shih-wei Liao
312ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  // Close the output before return.
313ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  delete out;
314ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang
315ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang  return err;
316ade92778b99382413ff9c556c724dd3f447e5dfbZonr Chang}
317b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
3181bd9f627fa0affb457507e86b0b6684c695fe726Stephen Hinesbool Compiler::addInternalizeSymbolsPass(Script &pScript, llvm::legacy::PassManager &pPM) {
319b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // Add a pass to internalize the symbols that don't need to have global
320b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // visibility.
321b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  RSScript &script = static_cast<RSScript &>(pScript);
322b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  llvm::Module &module = script.getSource().getModule();
323b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  bcinfo::MetadataExtractor me(&module);
324b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  if (!me.extract()) {
325b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    bccAssert(false && "Could not extract metadata for module!");
326b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    return false;
327b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  }
328b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
329b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // The vector contains the symbols that should not be internalized.
330b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  std::vector<const char *> export_symbols;
331b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
332107f50d54d9606e495187d0e89225d3d9fdc1fa9Stephen Hines  const char *sf[] = {
333fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRoot,               // Graphics drawing function or compute kernel.
334fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kInit,               // Initialization routine called implicitly on startup.
335fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsDtor,             // Static global destructor for a script instance.
336fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsInfo,             // Variable containing string of RS metadata info.
337fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsGlobalEntries,    // Optional number of global variables.
338fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsGlobalNames,      // Optional global variable name info.
339fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsGlobalAddresses,  // Optional global variable address info.
340fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsGlobalSizes,      // Optional global variable size info.
341fb81ec1a875d13d9750006313b9123903336101dStephen Hines    kRsGlobalProperties, // Optional global variable properties.
342fb81ec1a875d13d9750006313b9123903336101dStephen Hines    nullptr              // Must be nullptr-terminated.
343107f50d54d9606e495187d0e89225d3d9fdc1fa9Stephen Hines  };
344107f50d54d9606e495187d0e89225d3d9fdc1fa9Stephen Hines  const char **special_functions = sf;
345b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // Special RS functions should always be global symbols.
346b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  while (*special_functions != nullptr) {
347b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    export_symbols.push_back(*special_functions);
348b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    special_functions++;
349b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  }
350b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
351b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // Visibility of symbols appeared in rs_export_var and rs_export_func should
352b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  // also be preserved.
353b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  size_t exportVarCount = me.getExportVarCount();
354b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  size_t exportFuncCount = me.getExportFuncCount();
355b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  size_t exportForEachCount = me.getExportForEachSignatureCount();
3564e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala  size_t exportReduceCount = me.getExportReduceCount();
357b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  const char **exportVarNameList = me.getExportVarNameList();
358b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  const char **exportFuncNameList = me.getExportFuncNameList();
359b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  const char **exportForEachNameList = me.getExportForEachNameList();
360a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  const bcinfo::MetadataExtractor::Reduce *exportReduceList = me.getExportReduceList();
361b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  size_t i;
362b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
363b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  for (i = 0; i < exportVarCount; ++i) {
364b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    export_symbols.push_back(exportVarNameList[i]);
365b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  }
366b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
367b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  for (i = 0; i < exportFuncCount; ++i) {
368b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes    export_symbols.push_back(exportFuncNameList[i]);
369b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  }
370b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
371a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  // Expanded foreach functions should not be internalized; nor should
372a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  // general reduction initializer, combiner, and outconverter
373a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  // functions. keep_funcs keeps the names of these functions around
374a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  // until createInternalizePass() is finished making its own copy of
375a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  // the visible symbols.
376c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross  std::vector<std::string> keep_funcs;
377a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  keep_funcs.reserve(exportForEachCount + exportReduceCount*4);
3784e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala
379b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  for (i = 0; i < exportForEachCount; ++i) {
380c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross    keep_funcs.push_back(std::string(exportForEachNameList[i]) + ".expand");
3814e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala  }
382c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross  auto keepFuncsPushBackIfPresent = [&keep_funcs](const char *Name) {
383c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross    if (Name) keep_funcs.push_back(Name);
384c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross  };
385a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross  for (i = 0; i < exportReduceCount; ++i) {
386a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    keep_funcs.push_back(std::string(exportReduceList[i].mAccumulatorName) + ".expand");
387a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    keepFuncsPushBackIfPresent(exportReduceList[i].mInitializerName);
388a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    if (exportReduceList[i].mCombinerName != nullptr) {
389a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross      keep_funcs.push_back(exportReduceList[i].mCombinerName);
39057fd9f882f3359be4201c42b02aebf785d311df2David Gross    } else {
391a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross      keep_funcs.push_back(nameReduceCombinerFromAccumulator(exportReduceList[i].mAccumulatorName));
39257fd9f882f3359be4201c42b02aebf785d311df2David Gross    }
393a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    keepFuncsPushBackIfPresent(exportReduceList[i].mOutConverterName);
39479e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross  }
395b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
396c545d6f10fa4827de235b5f85b58e803eba725bcDavid Gross  for (auto &symbol_name : keep_funcs) {
3974e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala    export_symbols.push_back(symbol_name.c_str());
398b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  }
399b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
40010f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  // http://b/26165616 - WAR for this bug defines the __truncxfhf2 function in
40110f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  // frameworks/rs/driver/runtime.  Don't internalize this function for x86, so
40210f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  // that a script can find and link against it.
40310f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  llvm::Triple triple(getTargetMachine().getTargetTriple());
40410f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  if (triple.getArch() == llvm::Triple::x86) {
40510f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar    export_symbols.push_back("__truncxfhf2");
40610f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar  }
40710f2a8f1d60724c306d01cdd0682e38122637502Pirama Arumuga Nainar
408b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  pPM.add(llvm::createInternalizePass(export_symbols));
409b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
410b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  return true;
411b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes}
412b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
4135aefc98db2dc14a703ce3d4f134565b834686552David Grossvoid Compiler::addInvokeHelperPass(llvm::legacy::PassManager &pPM) {
414b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray  llvm::Triple arch(getTargetMachine().getTargetTriple());
415b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray  if (arch.isArch64Bit()) {
416b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray    pPM.add(createRSInvokeHelperPass());
417b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray  }
418b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray}
419b7bce7436876884dfd78ec41d147ddbe47e37cbdTim Murray
42009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leovoid Compiler::addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
42109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  if (pScript.getSource().getDebugInfoEnabled())
42209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    pPM.add(createRSAddDebugInfoPass());
42309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo}
42409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
4254e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Walavoid Compiler::addExpandKernelPass(llvm::legacy::PassManager &pPM) {
4264e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala  // Expand ForEach and reduce on CPU path to reduce launch overhead.
427b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes  bool pEnableStepOpt = true;
4284e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala  pPM.add(createRSKernelExpandPass(pEnableStepOpt));
429b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes}
430b4447cd2b14f53efd9102d28da48000be7b2d4fdChris Wailes
4315aefc98db2dc14a703ce3d4f134565b834686552David Grossvoid Compiler::addGlobalInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
432750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines  // Add additional information about RS global variables inside the Module.
433750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines  RSScript &script = static_cast<RSScript &>(pScript);
434750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines  if (script.getEmbedGlobalInfo()) {
435750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines    pPM.add(createRSGlobalInfoPass(script.getEmbedGlobalInfoSkipConstant()));
436750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines  }
437750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines}
438750ee65e129a2baef2dc5bb9ad210b45c9184926Stephen Hines
4395aefc98db2dc14a703ce3d4f134565b834686552David Grossvoid Compiler::addInvariantPass(llvm::legacy::PassManager &pPM) {
4401d93a190e62ec1588b4724ca8759216b2d0b76d7David Gross  // Mark Loads from RsExpandKernelDriverInfo as "load.invariant".
4411d93a190e62ec1588b4724ca8759216b2d0b76d7David Gross  // Should run after ExpandForEach and before inlining.
4421d93a190e62ec1588b4724ca8759216b2d0b76d7David Gross  pPM.add(createRSInvariantPass());
4438c24f8d1d75b619130e8bfce204ed9695362d4a1Pirama Arumuga Nainar}
444ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar
445ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainarenum Compiler::ErrorCode Compiler::screenGlobalFunctions(Script &pScript) {
446ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  llvm::Module &module = pScript.getSource().getModule();
447ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar
448ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  // Materialize the bitcode module in case this is a lazy-load module.  Do not
449ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  // clear the materializer by calling materializeAllPermanently since the
450ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  // runtime library has not been merged into the module yet.
451ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  if (module.getMaterializer() != nullptr) {
452ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar    std::error_code ec = module.materializeAll();
453ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar    if (ec) {
454ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar      ALOGE("Failed to materialize module `%s' when screening globals! (%s)",
455ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar            module.getModuleIdentifier().c_str(), ec.message().c_str());
456ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar      return kErrMaterialization;
457ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar    }
458ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  }
459ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar
460ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  // Add pass to check for illegal function calls.
461ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  llvm::legacy::PassManager pPM;
462ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  pPM.add(createRSScreenFunctionsPass());
463ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  pPM.run(module);
464ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar
465ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar  return kSuccess;
466ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar
467ebff2ead4ad622ff1bd3f3c108790cead62fe7c7Pirama Arumuga Nainar}
4689e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar
4699e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarvoid Compiler::translateGEPs(Script &pScript) {
4709e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  llvm::legacy::PassManager pPM;
4719e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  pPM.add(createRSX86TranslateGEPPass());
4729e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar
4739e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  // Materialization done in screenGlobalFunctions above.
4749e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar  pPM.run(pScript.getSource().getModule());
4759e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar}
476