blob: 1d57b543bda66e99655faea105b27a80f8718b1e [file] [log] [blame]
//===--- Passes.cpp - Swift Compiler SIL Pass Entrypoints -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file provides implementations of a few helper functions
/// which provide abstracted entrypoints to the SILPasses stage.
///
/// \note The actual SIL passes should be implemented in per-pass source files,
/// not in this file.
///
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-optimizer"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/YAMLParser.h"
using namespace swift;
bool swift::runSILDiagnosticPasses(SILModule &Module) {
auto &opts = Module.getOptions();
// Verify the module, if required.
if (opts.VerifyAll)
Module.verify();
// If we parsed a .sil file that is already in canonical form, don't rerun
// the diagnostic passes.
if (Module.getStage() != SILStage::Raw)
return false;
executePassPipelinePlan(&Module,
SILPassPipelinePlan::getDiagnosticPassPipeline(opts),
/*isMandatory*/ true);
// If we were asked to debug serialization, exit now.
auto &Ctx = Module.getASTContext();
if (opts.DebugSerialization)
return Ctx.hadError();
// Generate diagnostics.
Module.setStage(SILStage::Canonical);
// Verify the module, if required.
if (opts.VerifyAll)
Module.verify();
else {
LLVM_DEBUG(Module.verify());
}
// If errors were produced during SIL analysis, return true.
return Ctx.hadError();
}
bool swift::runSILOwnershipEliminatorPass(SILModule &Module) {
auto &Ctx = Module.getASTContext();
auto &opts = Module.getOptions();
executePassPipelinePlan(
&Module, SILPassPipelinePlan::getOwnershipEliminatorPassPipeline(opts));
return Ctx.hadError();
}
void swift::runSILOptimizationPasses(SILModule &Module) {
auto &opts = Module.getOptions();
// Verify the module, if required.
if (opts.VerifyAll)
Module.verify();
if (opts.DisableSILPerfOptimizations) {
// If we are not supposed to run SIL perf optzns, we may still need to
// serialize. So serialize now.
executePassPipelinePlan(
&Module, SILPassPipelinePlan::getSerializeSILPassPipeline(opts),
/*isMandatory*/ true);
return;
}
executePassPipelinePlan(
&Module, SILPassPipelinePlan::getPerformancePassPipeline(opts));
// Check if we actually serialized our module. If we did not, serialize now.
if (!Module.isSerialized()) {
executePassPipelinePlan(
&Module, SILPassPipelinePlan::getSerializeSILPassPipeline(opts),
/*isMandatory*/ true);
}
// If we were asked to debug serialization, exit now.
if (opts.DebugSerialization)
return;
// Verify the module, if required.
if (opts.VerifyAll)
Module.verify();
else {
LLVM_DEBUG(Module.verify());
}
}
void swift::runSILPassesForOnone(SILModule &Module) {
// Verify the module, if required.
if (Module.getOptions().VerifyAll)
Module.verify();
// We want to run the Onone passes also for function which have an explicit
// Onone attribute.
executePassPipelinePlan(
&Module, SILPassPipelinePlan::getOnonePassPipeline(Module.getOptions()),
/*isMandatory*/ true);
// Verify the module, if required.
if (Module.getOptions().VerifyAll)
Module.verify();
else {
LLVM_DEBUG(Module.verify());
}
}
void swift::runSILOptimizationPassesWithFileSpecification(SILModule &M,
StringRef Filename) {
auto &opts = M.getOptions();
executePassPipelinePlan(
&M, SILPassPipelinePlan::getPassPipelineFromFile(opts, Filename));
}
/// Get the Pass ID enum value from an ID string.
PassKind swift::PassKindFromString(StringRef IDString) {
return llvm::StringSwitch<PassKind>(IDString)
#define PASS(ID, TAG, DESCRIPTION) .Case(#ID, PassKind::ID)
#include "swift/SILOptimizer/PassManager/Passes.def"
.Default(PassKind::invalidPassKind);
}
/// Get an ID string for the given pass Kind.
/// This is useful for tools that identify a pass
/// by its type name.
StringRef swift::PassKindID(PassKind Kind) {
switch (Kind) {
#define PASS(ID, TAG, DESCRIPTION) \
case PassKind::ID: \
return #ID;
#include "swift/SILOptimizer/PassManager/Passes.def"
case PassKind::invalidPassKind:
llvm_unreachable("Invalid pass kind?!");
}
llvm_unreachable("Unhandled PassKind in switch.");
}
/// Get a tag string for the given pass Kind.
/// This format is useful for command line options.
StringRef swift::PassKindTag(PassKind Kind) {
switch (Kind) {
#define PASS(ID, TAG, DESCRIPTION) \
case PassKind::ID: \
return TAG;
#include "swift/SILOptimizer/PassManager/Passes.def"
case PassKind::invalidPassKind:
llvm_unreachable("Invalid pass kind?!");
}
llvm_unreachable("Unhandled PassKind in switch.");
}
// During SIL Lowering, passes may see partially lowered SIL, which is
// inconsistent with the current (canonical) stage. We don't change the SIL
// stage until lowering is complete. Consequently, any pass added to this
// PassManager needs to be able to handle the output of the previous pass. If
// the function pass needs to read SIL from other functions, it may be best to
// convert it to a module pass to ensure that the SIL input is always at the
// same stage of lowering.
void swift::runSILLoweringPasses(SILModule &Module) {
auto &opts = Module.getOptions();
executePassPipelinePlan(&Module,
SILPassPipelinePlan::getLoweringPassPipeline(opts),
/*isMandatory*/ true);
assert(Module.getStage() == SILStage::Lowered);
}