[Remarks] Add a specialized RemarkStreamer for SIL remarks

This allows the usage of the whole remark infrastructure developed in
LLVM, which includes a new binary format, metadata in object files, etc.

This gets rid of the YAMLTraits-based remark serialization and does the
plumbing for hooking to LLVM's main remark streamer.

For more about the idea behind LLVM's main remark streamer, see the
docs/Remarks.rst changes in https://reviews.llvm.org/D73676.

The flags are now:

* -save-optimization-record: enable remarks, defaults to YAML
* -save-optimization-record=<format>: enable remarks, use <format> for
serialization
* -save-optimization-record-passes <regex>: only serialize passes that
match <regex>.

The YAMLTraits in swift had a different `flow` setting for the debug
location, resulting in some test changes.
This commit is contained in:
Francis Visoiu Mistrih
2019-10-28 18:06:17 -07:00
parent e7b2850f52
commit e724ebab6b
29 changed files with 505 additions and 230 deletions

View File

@@ -372,6 +372,8 @@ NOTE(compiled_module_invalid_reason,none,
ERROR(unknown_forced_module_loading_mode,none,
"unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0'",
(StringRef))
ERROR(error_creating_remark_serializer,none,
"error while creating remark serializer: '%0'", (StringRef))
REMARK(interface_file_lock_failure,none,
"could not acquire lock file for module interface '%0'", (StringRef))

View File

@@ -23,6 +23,7 @@
#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Remarks/RemarkFormat.h"
#include <string>
#include <climits>
@@ -161,10 +162,17 @@ public:
/// pipeline or after serialization.
bool StripOwnershipAfterSerialization = true;
/// The name of the file to which the backend should save YAML optimization
/// The name of the file to which the backend should save optimization
/// records.
std::string OptRecordFile;
/// The regex that filters the passes that should be saved to the optimization
/// records.
std::string OptRecordPasses;
/// The format used for serializing remarks (default: YAML)
llvm::remarks::Format OptRecordFormat = llvm::remarks::Format::YAML;
SILOptions() {}
/// Return a hash code of any components from these options that should

View File

@@ -72,7 +72,8 @@ TYPE("tbd", TBD, "tbd", "")
TYPE("module-trace", ModuleTrace, "trace.json", "")
TYPE("index-data", IndexData, "", "")
TYPE("opt-record", OptRecord, "opt.yaml", "")
TYPE("yaml-opt-record", YAMLOptRecord, "opt.yaml", "")
TYPE("bitstream-opt-record",BitstreamOptRecord, "opt.bitstream", "")
// Overlay files declare wrapper modules, called "separately-imported overlays",
// that should be automatically imported when a particular module is imported.

View File

@@ -317,6 +317,9 @@ public:
virtual void validateArguments(DiagnosticEngine &diags,
const llvm::opt::ArgList &args,
StringRef defaultTarget) const {}
llvm::Expected<file_types::ID>
remarkFileTypeFromArgs(const llvm::opt::ArgList &Args) const;
};
} // end namespace driver
} // end namespace swift

View File

@@ -548,10 +548,20 @@ def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">,
def save_optimization_record : Flag<["-"], "save-optimization-record">,
Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
def save_optimization_record_EQ : Joined<["-"], "save-optimization-record=">,
Flags<[FrontendOption]>,
HelpText<"Generate an optimization record file in a specific format "
"(default: YAML)">, MetaVarName<"<format>">;
def save_optimization_record_path :
Separate<["-"], "save-optimization-record-path">,
Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Specify the file name of any generated YAML optimization record">;
HelpText<"Specify the file name of any generated optimization record">;
def save_optimization_record_passes :
Separate<["-"], "save-optimization-record-passes">,
Flags<[FrontendOption]>,
HelpText<"Only include passes which match a specified regular expression in"
"the generated optimization record "
"(by default, include all passes)">, MetaVarName<"<regex>">;
// Platform options.
def enable_app_extension : Flag<["-"], "application-extension">,

View File

@@ -20,6 +20,7 @@
#define SWIFT_SIL_OPTIMIZATIONREMARKEMITTER_H
#include "swift/Basic/SourceLoc.h"
#include "swift/Demangling/Demangler.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
@@ -75,9 +76,9 @@ template <typename DerivedT> class Remark {
StringRef passName;
/// Textual identifier for the remark (single-word, camel-case). Can be used
/// by external tools reading the YAML output file for optimization remarks to
/// by external tools reading the output file for optimization remarks to
/// identify the remark.
StringRef identifier;
SmallString<32> identifier;
/// Source location for the diagnostics.
SourceLoc location;
@@ -85,13 +86,20 @@ template <typename DerivedT> class Remark {
/// The function for the diagnostics.
SILFunction *function;
/// The demangled name of \p Function.
SmallString<64> demangledFunctionName;
/// Indentation used if this remarks is printed as a debug message.
unsigned indentDebugWidth = 0;
protected:
Remark(StringRef identifier, SILInstruction &i)
: identifier(identifier), location(i.getLoc().getSourceLoc()),
function(i.getParent()->getParent()) {}
: identifier((Twine("sil.") + identifier).str()),
location(i.getLoc().getSourceLoc()),
function(i.getParent()->getParent()),
demangledFunctionName(Demangle::demangleSymbolAsString(
function->getName(),
Demangle::DemangleOptions::SimplifiedUIDemangleOptions())) {}
public:
DerivedT &operator<<(StringRef s) {
@@ -112,11 +120,13 @@ public:
StringRef getPassName() const { return passName; }
StringRef getIdentifier() const { return identifier; }
SILFunction *getFunction() const { return function; }
StringRef getDemangledFunctionName() const { return demangledFunctionName; }
SourceLoc getLocation() const { return location; }
std::string getMsg() const;
std::string getDebugMsg() const;
Remark<DerivedT> &getRemark() { return *this; }
SmallVector<Argument, 4> &getArgs() { return args; }
ArrayRef<Argument> getArgs() const { return args; }
void setPassName(StringRef name) { passName = name; }
};
@@ -156,7 +166,7 @@ public:
void emit(T remarkBuilder, decltype(remarkBuilder()) * = nullptr) {
using RemarkT = decltype(remarkBuilder());
// Avoid building the remark unless remarks are enabled.
if (isEnabled<RemarkT>() || module.getOptRecordStream()) {
if (isEnabled<RemarkT>() || module.getSILRemarkStreamer()) {
auto rb = remarkBuilder();
rb.setPassName(passName);
emit(rb);
@@ -171,7 +181,7 @@ public:
using RemarkT = decltype(remarkBuilder());
// Avoid building the remark unless remarks are enabled.
bool emitRemark = emitter && (emitter->isEnabled<RemarkT>() ||
emitter->module.getOptRecordStream());
emitter->module.getSILRemarkStreamer());
// Same for DEBUG.
bool shouldEmitDebug = false;
#ifndef NDEBUG

View File

@@ -67,6 +67,7 @@ class SILUndef;
class SourceFile;
class SerializedSILLoader;
class SILFunctionBuilder;
class SILRemarkStreamer;
namespace Lowering {
class SILGenModule;
@@ -232,13 +233,11 @@ private:
// The list of SILProperties in the module.
PropertyListType properties;
/// This is the underlying raw stream of OptRecordStream.
///
/// It is also owned by SILModule in order to keep their lifetime in sync.
std::unique_ptr<llvm::raw_ostream> OptRecordRawStream;
/// The remark output stream used to record SIL remarks to a file.
std::unique_ptr<llvm::raw_fd_ostream> silRemarkStream;
/// If non-null, the YAML file where remarks should be recorded.
std::unique_ptr<llvm::yaml::Output> OptRecordStream;
/// The remark streamer used to serialize SIL remarks to a file.
std::unique_ptr<swift::SILRemarkStreamer> silRemarkStreamer;
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
@@ -524,9 +523,12 @@ public:
return coverageMaps;
}
llvm::yaml::Output *getOptRecordStream() { return OptRecordStream.get(); }
void setOptRecordStream(std::unique_ptr<llvm::yaml::Output> &&Stream,
std::unique_ptr<llvm::raw_ostream> &&RawStream);
swift::SILRemarkStreamer *getSILRemarkStreamer() {
return silRemarkStreamer.get();
}
void setSILRemarkStreamer(
std::unique_ptr<llvm::raw_fd_ostream> &&remarkStream,
std::unique_ptr<swift::SILRemarkStreamer> &&remarkStreamer);
// This is currently limited to VarDecl because the visibility of global
// variables and class properties is straightforward, while the visibility of

View File

@@ -0,0 +1,104 @@
//===--- SILRemarkStreamer.h - Interface for streaming remarks --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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 defines the interface used to stream SIL optimization diagnostics
/// through LLVM's RemarkStreamer interface.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_SILREMARKSTREAMER_H
#define SWIFT_SIL_SILREMARKSTREAMER_H
#include "swift/SIL/OptimizationRemark.h"
#include "llvm/Remarks/RemarkStreamer.h"
namespace swift {
class SILRemarkStreamer {
llvm::remarks::RemarkStreamer &llvmStreamer;
// Source manager for resolving source locations.
const SourceManager &srcMgr;
/// Convert diagnostics into LLVM remark objects.
/// The lifetime of the members of the result is bound to the lifetime of
/// the SIL remarks.
template <typename RemarkT>
llvm::remarks::Remark
toLLVMRemark(const OptRemark::Remark<RemarkT> &remark) const;
public:
SILRemarkStreamer(llvm::remarks::RemarkStreamer &llvmStreamer,
const SourceManager &srcMgr)
: llvmStreamer(llvmStreamer), srcMgr(srcMgr) {}
/// Emit a remark through the streamer.
template <typename RemarkT>
void emit(const OptRemark::Remark<RemarkT> &remark);
};
std::pair<std::unique_ptr<llvm::raw_fd_ostream>,
std::unique_ptr<SILRemarkStreamer>>
createSILRemarkStreamer(SILModule &srcMgr, StringRef filename, StringRef passes,
llvm::remarks::Format format,
DiagnosticEngine &diagEngine, SourceManager &sourceMgr);
// Implementation for template member functions.
// OptRemark type -> llvm::remarks::Type
template <typename RemarkT> static llvm::remarks::Type toRemarkType() {
if (std::is_same<RemarkT, OptRemark::RemarkPassed>::value)
return llvm::remarks::Type::Passed;
if (std::is_same<RemarkT, OptRemark::RemarkMissed>::value)
return llvm::remarks::Type::Missed;
llvm_unreachable("Unknown remark type");
}
static inline Optional<llvm::remarks::RemarkLocation>
toRemarkLocation(const SourceLoc &loc, const SourceManager &srcMgr) {
if (!loc.isValid())
return None;
StringRef file = srcMgr.getDisplayNameForLoc(loc);
unsigned line, col;
std::tie(line, col) = srcMgr.getLineAndColumn(loc);
return llvm::remarks::RemarkLocation{file, line, col};
}
template <typename RemarkT>
llvm::remarks::Remark SILRemarkStreamer::toLLVMRemark(
const OptRemark::Remark<RemarkT> &optRemark) const {
llvm::remarks::Remark llvmRemark; // The result.
llvmRemark.RemarkType = toRemarkType<RemarkT>();
llvmRemark.PassName = optRemark.getPassName();
llvmRemark.RemarkName = optRemark.getIdentifier();
llvmRemark.FunctionName = optRemark.getDemangledFunctionName();
llvmRemark.Loc = toRemarkLocation(optRemark.getLocation(), srcMgr);
for (const OptRemark::Argument &arg : optRemark.getArgs()) {
llvmRemark.Args.emplace_back();
llvmRemark.Args.back().Key = arg.key;
llvmRemark.Args.back().Val = arg.val;
llvmRemark.Args.back().Loc = toRemarkLocation(arg.loc, srcMgr);
}
return llvmRemark;
}
template <typename RemarkT>
void SILRemarkStreamer::emit(const OptRemark::Remark<RemarkT> &optRemark) {
if (!llvmStreamer.matchesFilter(optRemark.getPassName()))
return;
return llvmStreamer.getSerializer().emit(toLLVMRemark(optRemark));
}
} // namespace swift
#endif

View File

@@ -78,7 +78,7 @@ bool file_types::isTextual(ID Id) {
case file_types::TY_ImportedModules:
case file_types::TY_TBD:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftOverlayFile:
@@ -102,6 +102,7 @@ bool file_types::isTextual(ID Id) {
case file_types::TY_Nothing:
case file_types::TY_Remapping:
case file_types::TY_IndexData:
case file_types::TY_BitstreamOptRecord:
return false;
case file_types::TY_INVALID:
llvm_unreachable("Invalid type ID.");
@@ -146,7 +147,8 @@ bool file_types::isAfterLLVM(ID Id) {
case file_types::TY_Remapping:
case file_types::TY_IndexData:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
return false;
@@ -195,7 +197,8 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
case file_types::TY_Remapping:
case file_types::TY_IndexData:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
return false;
case file_types::TY_INVALID:
llvm_unreachable("Invalid type ID.");

View File

@@ -47,6 +47,7 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -1941,7 +1942,8 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
case file_types::TY_ImportedModules:
case file_types::TY_TBD:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftCrossImportDir:
@@ -2766,6 +2768,7 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
Output.get());
if (C.getArgs().hasArg(options::OPT_save_optimization_record,
options::OPT_save_optimization_record_EQ,
options::OPT_save_optimization_record_path))
chooseOptimizationRecordPath(C, workingDirectory, Buf, Output.get());
@@ -3202,12 +3205,18 @@ void Driver::chooseOptimizationRecordPath(Compilation &C,
CommandOutput *Output) const {
const OutputInfo &OI = C.getOutputInfo();
if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
llvm::Expected<file_types::ID> FileType =
C.getToolChain().remarkFileTypeFromArgs(C.getArgs());
if (!FileType) {
Diags.diagnose({}, diag::error_creating_remark_serializer,
llvm::toString(FileType.takeError()));
return;
}
auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
OI, C.getArgs(), options::OPT_save_optimization_record_path,
file_types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true,
workingDirectory, Buf);
OI, C.getArgs(), options::OPT_save_optimization_record_path, *FileType,
/*TreatAsTopLevelOutput=*/true, workingDirectory, Buf);
Output->setAdditionalOutputForType(file_types::TY_OptRecord, filename);
Output->setAdditionalOutputForType(*FileType, filename);
} else
// FIXME: We should use the OutputMap in this case.
Diags.diagnose({}, diag::warn_opt_remark_disabled);

View File

@@ -24,6 +24,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
@@ -340,3 +341,25 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
std::move(invocationInfo.FilelistInfos), sortedJobs, NextQuasiPID,
responseFileInfo);
}
llvm::Expected<file_types::ID>
ToolChain::remarkFileTypeFromArgs(const llvm::opt::ArgList &Args) const {
const Arg *A = Args.getLastArg(options::OPT_save_optimization_record_EQ);
if (!A)
return file_types::TY_YAMLOptRecord;
llvm::Expected<llvm::remarks::Format> FormatOrErr =
llvm::remarks::parseFormat(A->getValue());
if (llvm::Error E = FormatOrErr.takeError())
return std::move(E);
switch (*FormatOrErr) {
case llvm::remarks::Format::YAML:
return file_types::TY_YAMLOptRecord;
case llvm::remarks::Format::Bitstream:
return file_types::TY_BitstreamOptRecord;
default:
return llvm::createStringError(std::errc::invalid_argument,
"Unknown remark format.");
}
}

View File

@@ -423,8 +423,29 @@ ToolChain::constructInvocation(const CompileJobAction &job,
Arguments.push_back("-cross-module-optimization");
}
addOutputsOfType(Arguments, context.Output, context.Args,
file_types::TY_OptRecord, "-save-optimization-record-path");
file_types::ID remarksFileType = file_types::TY_YAMLOptRecord;
// If a specific format is specified for the remarks, forward that as is.
if (auto remarksFormat =
context.Args.getLastArg(options::OPT_save_optimization_record_EQ)) {
Arguments.push_back(context.Args.MakeArgString(
Twine("-save-optimization-record=") + remarksFormat->getValue()));
// If that's the case, add the proper output file for the type.
if (llvm::Expected<file_types::ID> fileType =
remarkFileTypeFromArgs(context.Args))
remarksFileType = *fileType;
else
consumeError(fileType.takeError()); // Don't report errors here. This will
// be reported later anyway.
}
addOutputsOfType(Arguments, context.Output, context.Args, remarksFileType,
"-save-optimization-record-path");
if (auto remarksFilter = context.Args.getLastArg(
options::OPT_save_optimization_record_passes)) {
Arguments.push_back("-save-optimization-record-passes");
Arguments.push_back(remarksFilter->getValue());
}
if (context.Args.hasArg(options::OPT_migrate_keep_objc_visibility)) {
Arguments.push_back("-migrate-keep-objc-visibility");
@@ -559,7 +580,8 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
case file_types::TY_CompiledSource:
case file_types::TY_ModuleTrace:
case file_types::TY_TBD:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftSourceInfoFile:
@@ -815,7 +837,8 @@ ToolChain::constructInvocation(const BackendJobAction &job,
case file_types::TY_CompiledSource:
case file_types::TY_Remapping:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_YAMLOptRecord:
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftSourceInfoFile:

View File

@@ -999,6 +999,20 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
Opts.EnableDynamicReplacementCanCallPreviousImplementation = !Args.hasArg(
OPT_disable_previous_implementation_calls_in_dynamic_replacements);
if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_EQ)) {
llvm::Expected<llvm::remarks::Format> formatOrErr =
llvm::remarks::parseFormat(A->getValue());
if (llvm::Error err = formatOrErr.takeError()) {
Diags.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
toString(std::move(err)));
return true;
}
Opts.OptRecordFormat = *formatOrErr;
}
if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_passes))
Opts.OptRecordPasses = A->getValue();
if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_path))
Opts.OptRecordFile = A->getValue();

View File

@@ -63,6 +63,7 @@
#include "swift/Serialization/SerializationOptions.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SIL/SILRemarkStreamer.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
#include "swift/Syntax/SyntaxNodes.h"
#include "swift/TBDGen/TBDGen.h"
@@ -75,6 +76,8 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/Option/Option.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -708,21 +711,6 @@ static void countStatsPostSILGen(UnifiedStatsReporter &Stats,
C.NumSILGenGlobalVariables += Module.getSILGlobalList().size();
}
static std::unique_ptr<llvm::raw_fd_ostream>
createOptRecordFile(StringRef Filename, DiagnosticEngine &DE) {
if (Filename.empty())
return nullptr;
std::error_code EC;
auto File = std::make_unique<llvm::raw_fd_ostream>(Filename, EC,
llvm::sys::fs::F_None);
if (EC) {
DE.diagnose(SourceLoc(), diag::cannot_open_file, Filename, EC.message());
return nullptr;
}
return File;
}
static bool precompileBridgingHeader(const CompilerInvocation &Invocation,
const CompilerInstance &Instance) {
auto clangImporter = static_cast<ClangImporter *>(
@@ -1532,14 +1520,10 @@ static bool performCompileStepsPostSILGen(
return Context.hadError();
}
std::unique_ptr<llvm::raw_fd_ostream> OptRecordFile =
createOptRecordFile(SILOpts.OptRecordFile, Instance.getDiags());
if (OptRecordFile) {
auto Output =
std::make_unique<llvm::yaml::Output>(*OptRecordFile,
&Instance.getSourceMgr());
SM->setOptRecordStream(std::move(Output), std::move(OptRecordFile));
}
auto pair = createSILRemarkStreamer(
*SM, SILOpts.OptRecordFile, SILOpts.OptRecordPasses,
SILOpts.OptRecordFormat, Instance.getDiags(), Instance.getSourceMgr());
SM->setSILRemarkStreamer(std::move(pair.first), std::move(pair.second));
// This is the action to be used to serialize SILModule.
// It may be invoked multiple times, but it will perform

View File

@@ -39,6 +39,7 @@ add_swift_host_library(swiftSIL STATIC
SILOpenedArchetypesTracker.cpp
SILPrinter.cpp
SILProfiler.cpp
SILRemarkStreamer.cpp
SILSuccessor.cpp
SILType.cpp
SILUndef.cpp

View File

@@ -20,8 +20,8 @@
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/Demangling/Demangler.h"
#include "swift/SIL/SILRemarkStreamer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
@@ -105,9 +105,8 @@ static void emitRemark(SILModule &module, const Remark<RemarkT> &remark,
Diag<ArgTypes...> id, bool diagEnabled) {
if (remark.getLocation().isInvalid())
return;
if (auto *out = module.getOptRecordStream())
// YAMLTraits takes a non-const reference even when outputting.
*out << const_cast<Remark<RemarkT> &>(remark);
if (auto *remarkStreamer = module.getSILRemarkStreamer())
remarkStreamer->emit(remark);
if (diagEnabled)
module.getASTContext().Diags.diagnose(remark.getLocation(), id,
remark.getMsg());
@@ -130,66 +129,3 @@ void Emitter::emitDebug(const RemarkPassed &remark) {
void Emitter::emitDebug(const RemarkMissed &remark) {
llvm::dbgs() << remark.getDebugMsg();
}
namespace llvm {
namespace yaml {
template <typename KindT> struct MappingTraits<Remark<KindT>> {
static void mapping(llvm::yaml::IO &io, Remark<KindT> &remark) {
assert(io.outputting() && "input not implemented");
if (io.mapTag("!Passed", std::is_same<KindT, RemarkPassed>::value))
;
else if (io.mapTag("!Missed", std::is_same<KindT, RemarkMissed>::value))
;
else
llvm_unreachable("Unknown remark type");
// The attributes are read-only for now since we're only support outputting
// them.
StringRef passName = remark.getPassName();
io.mapRequired("Pass", passName);
std::string id = (Twine("sil.") + remark.getIdentifier()).str();
io.mapRequired("Name", id);
SourceLoc loc = remark.getLocation();
if (!io.outputting() || loc.isValid())
io.mapOptional("DebugLoc", loc);
std::string fn = Demangle::demangleSymbolAsString(
remark.getFunction()->getName(),
Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
io.mapRequired("Function", fn);
io.mapOptional("Args", remark.getArgs());
}
};
template <> struct MappingTraits<SourceLoc> {
static void mapping(IO &io, SourceLoc &loc) {
assert(io.outputting() && "input not yet implemented");
SourceManager *srcMgr = static_cast<SourceManager *>(io.getContext());
StringRef file = srcMgr->getDisplayNameForLoc(loc);
unsigned line, col;
std::tie(line, col) = srcMgr->getLineAndColumn(loc);
io.mapRequired("File", file);
io.mapRequired("Line", line);
io.mapRequired("Column", col);
}
};
// Implement this as a mapping for now to get proper quotation for the value.
template <> struct MappingTraits<OptRemark::Argument> {
static void mapping(IO &io, OptRemark::Argument &a) {
assert(io.outputting() && "input not yet implemented");
io.mapRequired(a.key.data(), a.val);
if (a.loc.isValid())
io.mapOptional("DebugLoc", a.loc);
}
};
} // end namespace yaml
} // end namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(OptRemark::Argument)

View File

@@ -20,6 +20,7 @@
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/Notifications.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILRemarkStreamer.h"
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/Serialization/SerializedSILLoader.h"
@@ -689,11 +690,11 @@ void SILModule::serialize() {
setSerialized();
}
void SILModule::setOptRecordStream(
std::unique_ptr<llvm::yaml::Output> &&Stream,
std::unique_ptr<llvm::raw_ostream> &&RawStream) {
OptRecordStream = std::move(Stream);
OptRecordRawStream = std::move(RawStream);
void SILModule::setSILRemarkStreamer(
std::unique_ptr<llvm::raw_fd_ostream> &&remarkStream,
std::unique_ptr<swift::SILRemarkStreamer> &&remarkStreamer) {
silRemarkStream = std::move(remarkStream);
silRemarkStreamer = std::move(remarkStreamer);
}
bool SILModule::isStdlibModule() const {

View File

@@ -0,0 +1,63 @@
//===--- SILRemarkStreamer.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/SILRemarkStreamer.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVMContext.h"
#include "llvm/IR/LLVMContext.h"
using namespace swift;
std::pair<std::unique_ptr<llvm::raw_fd_ostream>,
std::unique_ptr<SILRemarkStreamer>>
swift::createSILRemarkStreamer(SILModule &silModule, StringRef filename,
StringRef passes, llvm::remarks::Format format,
DiagnosticEngine &diagEngine,
SourceManager &sourceMgr) {
if (filename.empty())
return {nullptr, nullptr};
std::error_code errorCode;
auto file = std::make_unique<llvm::raw_fd_ostream>(filename, errorCode,
llvm::sys::fs::F_None);
if (errorCode) {
diagEngine.diagnose(SourceLoc(), diag::cannot_open_file, filename,
errorCode.message());
return {nullptr, nullptr};
}
llvm::Expected<std::unique_ptr<llvm::remarks::RemarkSerializer>>
remarkSerializerOrErr = llvm::remarks::createRemarkSerializer(
format, llvm::remarks::SerializerMode::Separate, *file);
if (llvm::Error err = remarkSerializerOrErr.takeError()) {
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
toString(std::move(err)));
return {nullptr, nullptr};
}
auto mainRS = std::make_unique<llvm::remarks::RemarkStreamer>(
std::move(*remarkSerializerOrErr), filename);
llvm::remarks::RemarkStreamer &mainRemarkStreamer = *mainRS;
getGlobalLLVMContext().setMainRemarkStreamer(std::move(mainRS));
if (!passes.empty()) {
if (llvm::Error err = mainRemarkStreamer.setFilter(passes)) {
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
toString(std::move(err)));
return {nullptr, nullptr};
}
}
auto remarkStreamer =
std::make_unique<SILRemarkStreamer>(mainRemarkStreamer, sourceMgr);
return {std::move(file), std::move(remarkStreamer)};
}

View File

@@ -0,0 +1,31 @@
// RUN: %empty-directory(%t)
// RUN: %target-swiftc_driver -O -wmo -save-optimization-record=bitstream %s -module-name optrecordmod -o %t/opt-record 2>&1 | %FileCheck -allow-empty %s
// RUN: llvm-bcanalyzer -dump %t/optrecordmod.opt.bitstream | %FileCheck -check-prefix=BITSTREAM %s
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos
// CHECK-NOT: remark
var a: Int = 1
#sourceLocation(file: "custom.swift", line: 2000)
func foo() {
a = 2
}
#sourceLocation() // reset
public func bar() {
foo()
// BITSTREAM: <Remark NumWords=13 BlockCodeSize=4>
// BITSTREAM-NEXT: <Remark header abbrevid=4 op0=1 op1=0 op2=1 op3=2/>
// BITSTREAM-NEXT: <Remark debug location abbrevid=5 op0=3 op1=[[@LINE-3]] op2=3/>
// BITSTREAM-NEXT: <Argument with debug location abbrevid=7 op0=4 op1=5 op2=6 op3=2000 op4=6/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=7 op1=8/>
// BITSTREAM-NEXT: <Argument with debug location abbrevid=7 op0=9 op1=10 op2=3 op3=[[@LINE-7]] op4=13/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=7 op1=11/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=12 op1=13/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=7 op1=14/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=15 op1=16/>
// BITSTREAM-NEXT: <Argument abbrevid=8 op0=7 op1=17/>
// BITSTREAM-NEXT: </Remark>
}

View File

@@ -0,0 +1,20 @@
// RUN: not %target-swiftc_driver -wmo -save-optimization-record=unknown %s -module-name optrecordmod -o /dev/null 2>&1 | %FileCheck --check-prefix=ERROR-FORMAT %s
// ERROR-FORMAT: error while creating remark serializer: 'Unknown remark format: 'unknown''
// RUN: %target-swiftc_driver -wmo -save-optimization-record %s -module-name optrecordmod -o /dev/null 2>&1 -### | %FileCheck --check-prefix=YAML-PATH %s
// RUN: %target-swiftc_driver -wmo -save-optimization-record=yaml %s -module-name optrecordmod -o /dev/null 2>&1 -### | %FileCheck --check-prefix=YAML-PATH %s
// YAML-PATH: -save-optimization-record-path {{.*}}optrecordmod.opt.yaml
// RUN: %target-swiftc_driver -wmo -save-optimization-record=bitstream %s -module-name optrecordmod -o /dev/null 2>&1 -### | %FileCheck --check-prefix=BITSTREAM-PATH %s
// BITSTREAM-PATH: -save-optimization-record=bitstream
// BITSTREAM-PATH: -save-optimization-record-path {{.*}}optrecordmod.opt.bitstream
// RUN: %target-swiftc_driver -wmo -save-optimization-record -save-optimization-record-passes sil-inliner %s -module-name optrecordmod -o /dev/null 2>&1 -### | %FileCheck --check-prefix=FILTER-PASS %s
// FILTER-PASS: -save-optimization-record-passes sil-inliner
var a: Int = 1
#sourceLocation(file: "custom.swift", line: 2000)
func foo() {
a = 2
}
#sourceLocation() // reset

View File

@@ -3,12 +3,16 @@
// RUN: %FileCheck -check-prefix=YAML %s < %t/optrecordmod.opt.yaml
// RUN: %target-swiftc_driver -O -wmo -save-optimization-record-path %t/specified.opt.yaml %s -module-name optrecordmod -o %t/opt-record 2>&1 | %FileCheck -allow-empty %s
// RUN: %FileCheck -check-prefix=YAML %s < %t/specified.opt.yaml
// RUN: %target-swiftc_driver -O -wmo -save-optimization-record -save-optimization-record-passes sil-inliner %s -module-name optrecordmod -o %t/opt-record 2>&1 | %FileCheck -allow-empty %s
// RUN: %FileCheck -check-prefix=YAML %s < %t/optrecordmod.opt.yaml
// RUN: %target-swiftc_driver -O -wmo -save-optimization-record -save-optimization-record-passes unknown -save-optimization-record-path %t/optrecordmod-filtered.opt.yaml %s -module-name optrecordmod -o %t/opt-record 2>&1 | %FileCheck -allow-empty %s
// RUN: %FileCheck -allow-empty -check-prefix=YAML-FILTERED %s < %t/optrecordmod-filtered.opt.yaml
// CHECK-NOT: remark
var a: Int = 1
#sourceLocation(file: "custom.swuft", line: 2000)
#sourceLocation(file: "custom.swift", line: 2000)
func foo() {
a = 2
}
@@ -20,22 +24,22 @@ public func bar() {
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: sil.Inlined
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}opt-record.swift
// YAML-NEXT: Line: [[@LINE-6]]
// YAML-NEXT: Column: 3
// YAML: File: {{.*}}opt-record.swift
// YAML: Line: [[@LINE-6]]
// YAML: Column: 3
// YAML-NEXT: Function: 'bar()'
// YAML-NEXT: Args:
// YAML-NEXT: - Callee: '"optrecordmod.foo()"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: custom.swuft
// YAML-NEXT: Line: 2000
// YAML-NEXT: Column: 6
// YAML: File: custom.swift
// YAML: Line: 2000
// YAML: Column: 6
// YAML-NEXT: - String: ' inlined into '
// YAML-NEXT: - Caller: '"optrecordmod.bar()"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}opt-record.swift
// YAML-NEXT: Line: [[@LINE-20]]
// YAML-NEXT: Column: 13
// YAML: File: {{.*}}opt-record.swift
// YAML: Line: [[@LINE-20]]
// YAML: Column: 13
// YAML-NEXT: - String: ' (cost = '
// YAML-NEXT: - Cost: '{{.*}}'
// YAML-NEXT: - String: ', benefit = '
@@ -43,3 +47,5 @@ public func bar() {
// YAML-NEXT: - String: ')'
// YAML-NEXT: ...
}
// YAML-FILTERED-NOT: sil-inliner

View File

@@ -33,17 +33,17 @@ sil hidden_external [transparent] [thunk] @witness_thunk2 : $@convention(witness
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.WitnessMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirt_class_witness_method.sil
// YAML-NEXT: Line: 55
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirt_class_witness_method.sil
// YAML: Line: 55
// YAML: Column: 8
// YAML-NEXT: Function: caller
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to '
// YAML-NEXT: - Method: '"witness_thunk"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirt_class_witness_method.sil
// YAML-NEXT: Line: 19
// YAML-NEXT: Column: 44
// YAML: File: {{.*}}/devirt_class_witness_method.sil
// YAML: Line: 19
// YAML: Column: 44
// YAML-NEXT: ...
sil hidden @caller : $@convention(thin) <T, U> (@owned C<T, U>) -> () {

View File

@@ -98,9 +98,9 @@ class Sub7 : Base {
// YAML: Pass: sil-speculative-devirtualizer
// YAML-NEXT: Name: sil.PartialSpecDevirt
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirt_speculate.swift
// YAML-NEXT: Line: 118
// YAML-NEXT: Column: 5
// YAML: File: {{.*}}/devirt_speculate.swift
// YAML: Line: 118
// YAML: Column: 5
// YAML-NEXT: Function: 'testMaxNumSpeculativeTargets(_:)'
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Partially devirtualized call with run-time checks for '

View File

@@ -24,17 +24,17 @@ sil_global @x : $Bar
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 47
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 47
// YAML: Column: 8
// YAML-NEXT: Function: function_with_cm
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 53
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 53
// YAML: Column: 6
// YAML-NEXT: ...
sil @function_with_cm : $@convention(thin) () -> () {
@@ -82,17 +82,17 @@ bb0(%0 : $Node):
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 74
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 74
// YAML: Column: 8
// YAML-NEXT: Function: class_method_apply
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"transparent_target"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 100
// YAML-NEXT: Column: 39
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 100
// YAML: Column: 39
// YAML-NEXT: ...
@@ -134,17 +134,17 @@ bb0(%0 : $@thick C.Type):
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 127
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 127
// YAML: Column: 8
// YAML-NEXT: Function: 'caller(_:)'
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize.sil
// YAML-NEXT: Line: 118
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}/devirtualize.sil
// YAML: Line: 118
// YAML: Column: 6
// YAML-NEXT: ...
sil_vtable B {

View File

@@ -25,17 +25,17 @@ sil_global @x : $Bar
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 46
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 46
// YAML: Column: 8
// YAML-NEXT: Function: function_with_cm
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 52
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 52
// YAML: Column: 6
// YAML-NEXT: ...
sil [ossa] @function_with_cm : $@convention(thin) () -> () {
@@ -83,17 +83,17 @@ bb0(%0 : @guaranteed $Node):
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 75
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 75
// YAML: Column: 8
// YAML-NEXT: Function: class_method_apply
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"transparent_target"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 101
// YAML-NEXT: Column: 46
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 101
// YAML: Column: 46
// YAML-NEXT: ...
@@ -135,17 +135,17 @@ bb0(%0 : $@thick C.Type):
// YAML-NEXT: Pass: sil-devirtualizer
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 128
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 128
// YAML: Column: 8
// YAML-NEXT: Function: 'caller(_:)'
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Devirtualized call to class method '
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
// YAML-NEXT: Line: 119
// YAML-NEXT: Column: 13
// YAML: File: {{.*}}/devirtualize_ownership.sil
// YAML: Line: 119
// YAML: Column: 13
// YAML-NEXT: ...
sil_vtable B {

View File

@@ -198,22 +198,22 @@ bb0:
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: sil.Inlined
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 223
// YAML-NEXT: Column: 3
// YAML: File: {{.*}}inliner_coldblocks.sil
// YAML: Line: 223
// YAML: Column: 3
// YAML-NEXT: Function: regular_large_callee
// YAML-NEXT: Args:
// YAML-NEXT: - Callee: '"update_global"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 20
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}inliner_coldblocks.sil
// YAML: Line: 20
// YAML: Column: 6
// YAML-NEXT: - String: ' inlined into '
// YAML-NEXT: - Caller: '"regular_large_callee"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 162
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}inliner_coldblocks.sil
// YAML: Line: 162
// YAML: Column: 6
// YAML-NEXT: - String: ' (cost = '
// YAML-NEXT: - Cost: '{{.*}}'
// YAML-NEXT: - String: ', benefit = '
@@ -238,17 +238,17 @@ bb0:
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: sil.NoInlinedCost
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 258
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}inliner_coldblocks.sil
// YAML: Line: 258
// YAML: Column: 8
// YAML-NEXT: Function: dont_inline_regular_large_callee
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Not profitable to inline function '
// YAML-NEXT: - Callee: '"regular_large_callee"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 162
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}inliner_coldblocks.sil
// YAML: Line: 162
// YAML: Column: 6
// YAML-NEXT: - String: ' (cost = '
// YAML-NEXT: - Cost: '{{.*}}'
// YAML-NEXT: - String: ', benefit = '

View File

@@ -23,17 +23,17 @@ import Swift
// YAML-NEXT: Pass: sil-generic-specializer
// YAML-NEXT: Name: sil.Specialized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 132
// YAML-NEXT: Column: 8
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 132
// YAML: Column: 8
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_init"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 73
// YAML-NEXT: Column: 17
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 73
// YAML: Column: 17
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(Int32, @thin XXX<Int32>.Type) -> XXX<Int32>'
// YAML-NEXT: ...
@@ -41,17 +41,17 @@ import Swift
// YAML-NEXT: Pass: sil-generic-specializer
// YAML-NEXT: Name: sil.Specialized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 142
// YAML-NEXT: Column: 9
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 142
// YAML: Column: 9
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_foo"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 90
// YAML-NEXT: Column: 17
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 90
// YAML: Column: 17
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(Int32, @inout XXX<Int32>) -> Int32'
// YAML-NEXT: ...
@@ -283,15 +283,15 @@ bb0(%0 : $Base):
// CHECK: return %0 : $Base
// YAML: Line: 277
// YAML-NEXT: Column: 8
// YAML: Column: 8
// YAML-NEXT: Function: specialize_generic_upcast
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"generic_upcast"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 268
// YAML-NEXT: Column: 6
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 268
// YAML: Column: 6
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(@owned Base) -> @owned Base'
// YAML-NEXT: ...

View File

@@ -10,17 +10,17 @@ sil_stage canonical
// CHECK-NEXT: Pass: sil-generic-specializer
// CHECK-NEXT: Name: sil.NoDef
// CHECK-NEXT: DebugLoc:
// CHECK-NEXT: File: {{.*}}/specialize_no_definition.sil
// CHECK-NEXT: Line: 36
// CHECK-NEXT: Column: 8
// CHECK: File: {{.*}}/specialize_no_definition.sil
// CHECK: Line: 36
// CHECK: Column: 8
// CHECK-NEXT: Function: foo
// CHECK-NEXT: Args:
// CHECK-NEXT: - String: 'Unable to specialize generic function '
// CHECK-NEXT: - Callee: '"bar"'
// CHECK-NEXT: DebugLoc:
// CHECK-NEXT: File: {{.*}}/specialize_no_definition.sil
// CHECK-NEXT: Line: 35
// CHECK-NEXT: Column: 21
// CHECK: File: {{.*}}/specialize_no_definition.sil
// CHECK: Line: 35
// CHECK: Column: 21
// CHECK-NEXT: - String: ' since definition is not visible'
// CHECK-NEXT: ...

View File

@@ -24,6 +24,7 @@
#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/SIL/SILRemarkStreamer.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
@@ -256,6 +257,20 @@ static cl::opt<std::string>
cl::desc("YAML output filename for pass remarks"),
cl::value_desc("filename"));
static cl::opt<std::string> RemarksPasses(
"save-optimization-record-passes",
cl::desc("Only include passes which match a specified regular expression "
"in the generated optimization record (by default, include all "
"passes)"),
cl::value_desc("regex"));
// sil-opt doesn't have the equivalent of -save-optimization-record=<format>.
// Instead, use -save-optimization-record-format <format>.
static cl::opt<std::string> RemarksFormat(
"save-optimization-record-format",
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));
static void runCommandLineSelectedPasses(SILModule *Module,
irgen::IRGenModule *IRGenMod) {
SILPassManager PM(Module, IRGenMod);
@@ -402,7 +417,8 @@ int main(int argc, char **argv) {
CI.performSema();
// If parsing produced an error, don't run any passes.
if (CI.getASTContext().hadError())
bool HadError = CI.getASTContext().hadError();
if (HadError)
return 1;
// Load the SIL if we have a module. We have to do this after SILParse
@@ -428,19 +444,24 @@ int main(int argc, char **argv) {
if (CI.getSILModule())
CI.getSILModule()->setSerializeSILAction([]{});
std::unique_ptr<llvm::raw_fd_ostream> OptRecordFile;
if (RemarksFilename != "") {
std::error_code EC;
OptRecordFile = std::make_unique<llvm::raw_fd_ostream>(
RemarksFilename, EC, llvm::sys::fs::F_None);
if (EC) {
llvm::errs() << EC.message() << '\n';
return 1;
llvm::remarks::Format remarksFormat = llvm::remarks::Format::YAML;
llvm::Expected<llvm::remarks::Format> formatOrErr =
llvm::remarks::parseFormat(RemarksFormat);
if (llvm::Error E = formatOrErr.takeError()) {
CI.getDiags().diagnose(SourceLoc(),
diag::error_creating_remark_serializer,
toString(std::move(E)));
HadError = true;
} else {
remarksFormat = *formatOrErr;
}
auto Stream = std::make_unique<llvm::yaml::Output>(*OptRecordFile,
&CI.getSourceMgr());
CI.getSILModule()->setOptRecordStream(std::move(Stream),
std::move(OptRecordFile));
auto Pair = createSILRemarkStreamer(*CI.getSILModule(), RemarksFilename,
RemarksPasses, remarksFormat,
CI.getDiags(), CI.getSourceMgr());
CI.getSILModule()->setSILRemarkStreamer(std::move(Pair.first),
std::move(Pair.second));
}
if (OptimizationGroup == OptGroup::Diagnostics) {
@@ -504,7 +525,7 @@ int main(int argc, char **argv) {
}
}
bool HadError = CI.getASTContext().hadError();
HadError |= CI.getASTContext().hadError();
// If we're in -verify mode, we've buffered up all of the generated
// diagnostics. Check now to ensure that they meet our expectations.