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