mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -372,6 +372,8 @@ NOTE(compiled_module_invalid_reason,none,
|
|||||||
ERROR(unknown_forced_module_loading_mode,none,
|
ERROR(unknown_forced_module_loading_mode,none,
|
||||||
"unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0'",
|
"unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0'",
|
||||||
(StringRef))
|
(StringRef))
|
||||||
|
ERROR(error_creating_remark_serializer,none,
|
||||||
|
"error while creating remark serializer: '%0'", (StringRef))
|
||||||
|
|
||||||
REMARK(interface_file_lock_failure,none,
|
REMARK(interface_file_lock_failure,none,
|
||||||
"could not acquire lock file for module interface '%0'", (StringRef))
|
"could not acquire lock file for module interface '%0'", (StringRef))
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "swift/Basic/OptimizationMode.h"
|
#include "swift/Basic/OptimizationMode.h"
|
||||||
#include "llvm/ADT/Hashing.h"
|
#include "llvm/ADT/Hashing.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Remarks/RemarkFormat.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
@@ -161,10 +162,17 @@ public:
|
|||||||
/// pipeline or after serialization.
|
/// pipeline or after serialization.
|
||||||
bool StripOwnershipAfterSerialization = true;
|
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.
|
/// records.
|
||||||
std::string OptRecordFile;
|
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() {}
|
SILOptions() {}
|
||||||
|
|
||||||
/// Return a hash code of any components from these options that should
|
/// Return a hash code of any components from these options that should
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ TYPE("tbd", TBD, "tbd", "")
|
|||||||
TYPE("module-trace", ModuleTrace, "trace.json", "")
|
TYPE("module-trace", ModuleTrace, "trace.json", "")
|
||||||
|
|
||||||
TYPE("index-data", IndexData, "", "")
|
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",
|
// Overlay files declare wrapper modules, called "separately-imported overlays",
|
||||||
// that should be automatically imported when a particular module is imported.
|
// that should be automatically imported when a particular module is imported.
|
||||||
|
|||||||
@@ -317,6 +317,9 @@ public:
|
|||||||
virtual void validateArguments(DiagnosticEngine &diags,
|
virtual void validateArguments(DiagnosticEngine &diags,
|
||||||
const llvm::opt::ArgList &args,
|
const llvm::opt::ArgList &args,
|
||||||
StringRef defaultTarget) const {}
|
StringRef defaultTarget) const {}
|
||||||
|
|
||||||
|
llvm::Expected<file_types::ID>
|
||||||
|
remarkFileTypeFromArgs(const llvm::opt::ArgList &Args) const;
|
||||||
};
|
};
|
||||||
} // end namespace driver
|
} // end namespace driver
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|||||||
@@ -548,10 +548,20 @@ def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">,
|
|||||||
|
|
||||||
def save_optimization_record : Flag<["-"], "save-optimization-record">,
|
def save_optimization_record : Flag<["-"], "save-optimization-record">,
|
||||||
Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
|
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 :
|
def save_optimization_record_path :
|
||||||
Separate<["-"], "save-optimization-record-path">,
|
Separate<["-"], "save-optimization-record-path">,
|
||||||
Flags<[FrontendOption, ArgumentIsPath]>,
|
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.
|
// Platform options.
|
||||||
def enable_app_extension : Flag<["-"], "application-extension">,
|
def enable_app_extension : Flag<["-"], "application-extension">,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define SWIFT_SIL_OPTIMIZATIONREMARKEMITTER_H
|
#define SWIFT_SIL_OPTIMIZATIONREMARKEMITTER_H
|
||||||
|
|
||||||
#include "swift/Basic/SourceLoc.h"
|
#include "swift/Basic/SourceLoc.h"
|
||||||
|
#include "swift/Demangling/Demangler.h"
|
||||||
#include "swift/SIL/SILBasicBlock.h"
|
#include "swift/SIL/SILBasicBlock.h"
|
||||||
#include "swift/SIL/SILInstruction.h"
|
#include "swift/SIL/SILInstruction.h"
|
||||||
#include "swift/SIL/SILModule.h"
|
#include "swift/SIL/SILModule.h"
|
||||||
@@ -75,9 +76,9 @@ template <typename DerivedT> class Remark {
|
|||||||
StringRef passName;
|
StringRef passName;
|
||||||
|
|
||||||
/// Textual identifier for the remark (single-word, camel-case). Can be used
|
/// 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.
|
/// identify the remark.
|
||||||
StringRef identifier;
|
SmallString<32> identifier;
|
||||||
|
|
||||||
/// Source location for the diagnostics.
|
/// Source location for the diagnostics.
|
||||||
SourceLoc location;
|
SourceLoc location;
|
||||||
@@ -85,13 +86,20 @@ template <typename DerivedT> class Remark {
|
|||||||
/// The function for the diagnostics.
|
/// The function for the diagnostics.
|
||||||
SILFunction *function;
|
SILFunction *function;
|
||||||
|
|
||||||
|
/// The demangled name of \p Function.
|
||||||
|
SmallString<64> demangledFunctionName;
|
||||||
|
|
||||||
/// Indentation used if this remarks is printed as a debug message.
|
/// Indentation used if this remarks is printed as a debug message.
|
||||||
unsigned indentDebugWidth = 0;
|
unsigned indentDebugWidth = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Remark(StringRef identifier, SILInstruction &i)
|
Remark(StringRef identifier, SILInstruction &i)
|
||||||
: identifier(identifier), location(i.getLoc().getSourceLoc()),
|
: identifier((Twine("sil.") + identifier).str()),
|
||||||
function(i.getParent()->getParent()) {}
|
location(i.getLoc().getSourceLoc()),
|
||||||
|
function(i.getParent()->getParent()),
|
||||||
|
demangledFunctionName(Demangle::demangleSymbolAsString(
|
||||||
|
function->getName(),
|
||||||
|
Demangle::DemangleOptions::SimplifiedUIDemangleOptions())) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DerivedT &operator<<(StringRef s) {
|
DerivedT &operator<<(StringRef s) {
|
||||||
@@ -112,11 +120,13 @@ public:
|
|||||||
StringRef getPassName() const { return passName; }
|
StringRef getPassName() const { return passName; }
|
||||||
StringRef getIdentifier() const { return identifier; }
|
StringRef getIdentifier() const { return identifier; }
|
||||||
SILFunction *getFunction() const { return function; }
|
SILFunction *getFunction() const { return function; }
|
||||||
|
StringRef getDemangledFunctionName() const { return demangledFunctionName; }
|
||||||
SourceLoc getLocation() const { return location; }
|
SourceLoc getLocation() const { return location; }
|
||||||
std::string getMsg() const;
|
std::string getMsg() const;
|
||||||
std::string getDebugMsg() const;
|
std::string getDebugMsg() const;
|
||||||
Remark<DerivedT> &getRemark() { return *this; }
|
Remark<DerivedT> &getRemark() { return *this; }
|
||||||
SmallVector<Argument, 4> &getArgs() { return args; }
|
SmallVector<Argument, 4> &getArgs() { return args; }
|
||||||
|
ArrayRef<Argument> getArgs() const { return args; }
|
||||||
|
|
||||||
void setPassName(StringRef name) { passName = name; }
|
void setPassName(StringRef name) { passName = name; }
|
||||||
};
|
};
|
||||||
@@ -156,7 +166,7 @@ public:
|
|||||||
void emit(T remarkBuilder, decltype(remarkBuilder()) * = nullptr) {
|
void emit(T remarkBuilder, decltype(remarkBuilder()) * = nullptr) {
|
||||||
using RemarkT = decltype(remarkBuilder());
|
using RemarkT = decltype(remarkBuilder());
|
||||||
// Avoid building the remark unless remarks are enabled.
|
// Avoid building the remark unless remarks are enabled.
|
||||||
if (isEnabled<RemarkT>() || module.getOptRecordStream()) {
|
if (isEnabled<RemarkT>() || module.getSILRemarkStreamer()) {
|
||||||
auto rb = remarkBuilder();
|
auto rb = remarkBuilder();
|
||||||
rb.setPassName(passName);
|
rb.setPassName(passName);
|
||||||
emit(rb);
|
emit(rb);
|
||||||
@@ -171,7 +181,7 @@ public:
|
|||||||
using RemarkT = decltype(remarkBuilder());
|
using RemarkT = decltype(remarkBuilder());
|
||||||
// Avoid building the remark unless remarks are enabled.
|
// Avoid building the remark unless remarks are enabled.
|
||||||
bool emitRemark = emitter && (emitter->isEnabled<RemarkT>() ||
|
bool emitRemark = emitter && (emitter->isEnabled<RemarkT>() ||
|
||||||
emitter->module.getOptRecordStream());
|
emitter->module.getSILRemarkStreamer());
|
||||||
// Same for DEBUG.
|
// Same for DEBUG.
|
||||||
bool shouldEmitDebug = false;
|
bool shouldEmitDebug = false;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class SILUndef;
|
|||||||
class SourceFile;
|
class SourceFile;
|
||||||
class SerializedSILLoader;
|
class SerializedSILLoader;
|
||||||
class SILFunctionBuilder;
|
class SILFunctionBuilder;
|
||||||
|
class SILRemarkStreamer;
|
||||||
|
|
||||||
namespace Lowering {
|
namespace Lowering {
|
||||||
class SILGenModule;
|
class SILGenModule;
|
||||||
@@ -232,13 +233,11 @@ private:
|
|||||||
// The list of SILProperties in the module.
|
// The list of SILProperties in the module.
|
||||||
PropertyListType properties;
|
PropertyListType properties;
|
||||||
|
|
||||||
/// This is the underlying raw stream of OptRecordStream.
|
/// The remark output stream used to record SIL remarks to a file.
|
||||||
///
|
std::unique_ptr<llvm::raw_fd_ostream> silRemarkStream;
|
||||||
/// It is also owned by SILModule in order to keep their lifetime in sync.
|
|
||||||
std::unique_ptr<llvm::raw_ostream> OptRecordRawStream;
|
|
||||||
|
|
||||||
/// If non-null, the YAML file where remarks should be recorded.
|
/// The remark streamer used to serialize SIL remarks to a file.
|
||||||
std::unique_ptr<llvm::yaml::Output> OptRecordStream;
|
std::unique_ptr<swift::SILRemarkStreamer> silRemarkStreamer;
|
||||||
|
|
||||||
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
|
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
|
||||||
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
|
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
|
||||||
@@ -524,9 +523,12 @@ public:
|
|||||||
return coverageMaps;
|
return coverageMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::yaml::Output *getOptRecordStream() { return OptRecordStream.get(); }
|
swift::SILRemarkStreamer *getSILRemarkStreamer() {
|
||||||
void setOptRecordStream(std::unique_ptr<llvm::yaml::Output> &&Stream,
|
return silRemarkStreamer.get();
|
||||||
std::unique_ptr<llvm::raw_ostream> &&RawStream);
|
}
|
||||||
|
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
|
// This is currently limited to VarDecl because the visibility of global
|
||||||
// variables and class properties is straightforward, while the visibility of
|
// variables and class properties is straightforward, while the visibility of
|
||||||
|
|||||||
104
include/swift/SIL/SILRemarkStreamer.h
Normal file
104
include/swift/SIL/SILRemarkStreamer.h
Normal 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
|
||||||
@@ -78,7 +78,7 @@ bool file_types::isTextual(ID Id) {
|
|||||||
case file_types::TY_ImportedModules:
|
case file_types::TY_ImportedModules:
|
||||||
case file_types::TY_TBD:
|
case file_types::TY_TBD:
|
||||||
case file_types::TY_ModuleTrace:
|
case file_types::TY_ModuleTrace:
|
||||||
case file_types::TY_OptRecord:
|
case file_types::TY_YAMLOptRecord:
|
||||||
case file_types::TY_SwiftModuleInterfaceFile:
|
case file_types::TY_SwiftModuleInterfaceFile:
|
||||||
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
||||||
case file_types::TY_SwiftOverlayFile:
|
case file_types::TY_SwiftOverlayFile:
|
||||||
@@ -102,6 +102,7 @@ bool file_types::isTextual(ID Id) {
|
|||||||
case file_types::TY_Nothing:
|
case file_types::TY_Nothing:
|
||||||
case file_types::TY_Remapping:
|
case file_types::TY_Remapping:
|
||||||
case file_types::TY_IndexData:
|
case file_types::TY_IndexData:
|
||||||
|
case file_types::TY_BitstreamOptRecord:
|
||||||
return false;
|
return false;
|
||||||
case file_types::TY_INVALID:
|
case file_types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID.");
|
llvm_unreachable("Invalid type ID.");
|
||||||
@@ -146,7 +147,8 @@ bool file_types::isAfterLLVM(ID Id) {
|
|||||||
case file_types::TY_Remapping:
|
case file_types::TY_Remapping:
|
||||||
case file_types::TY_IndexData:
|
case file_types::TY_IndexData:
|
||||||
case file_types::TY_ModuleTrace:
|
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_SwiftModuleInterfaceFile:
|
||||||
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
||||||
return false;
|
return false;
|
||||||
@@ -195,7 +197,8 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
|
|||||||
case file_types::TY_Remapping:
|
case file_types::TY_Remapping:
|
||||||
case file_types::TY_IndexData:
|
case file_types::TY_IndexData:
|
||||||
case file_types::TY_ModuleTrace:
|
case file_types::TY_ModuleTrace:
|
||||||
case file_types::TY_OptRecord:
|
case file_types::TY_YAMLOptRecord:
|
||||||
|
case file_types::TY_BitstreamOptRecord:
|
||||||
return false;
|
return false;
|
||||||
case file_types::TY_INVALID:
|
case file_types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID.");
|
llvm_unreachable("Invalid type ID.");
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "llvm/Option/Arg.h"
|
#include "llvm/Option/Arg.h"
|
||||||
#include "llvm/Option/ArgList.h"
|
#include "llvm/Option/ArgList.h"
|
||||||
#include "llvm/Option/OptTable.h"
|
#include "llvm/Option/OptTable.h"
|
||||||
|
#include "llvm/Remarks/RemarkFormat.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FileSystem.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_ImportedModules:
|
||||||
case file_types::TY_TBD:
|
case file_types::TY_TBD:
|
||||||
case file_types::TY_ModuleTrace:
|
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_SwiftModuleInterfaceFile:
|
||||||
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
||||||
case file_types::TY_SwiftCrossImportDir:
|
case file_types::TY_SwiftCrossImportDir:
|
||||||
@@ -2766,6 +2768,7 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
|
|||||||
Output.get());
|
Output.get());
|
||||||
|
|
||||||
if (C.getArgs().hasArg(options::OPT_save_optimization_record,
|
if (C.getArgs().hasArg(options::OPT_save_optimization_record,
|
||||||
|
options::OPT_save_optimization_record_EQ,
|
||||||
options::OPT_save_optimization_record_path))
|
options::OPT_save_optimization_record_path))
|
||||||
chooseOptimizationRecordPath(C, workingDirectory, Buf, Output.get());
|
chooseOptimizationRecordPath(C, workingDirectory, Buf, Output.get());
|
||||||
|
|
||||||
@@ -3202,12 +3205,18 @@ void Driver::chooseOptimizationRecordPath(Compilation &C,
|
|||||||
CommandOutput *Output) const {
|
CommandOutput *Output) const {
|
||||||
const OutputInfo &OI = C.getOutputInfo();
|
const OutputInfo &OI = C.getOutputInfo();
|
||||||
if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
|
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(
|
auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
|
||||||
OI, C.getArgs(), options::OPT_save_optimization_record_path,
|
OI, C.getArgs(), options::OPT_save_optimization_record_path, *FileType,
|
||||||
file_types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true,
|
/*TreatAsTopLevelOutput=*/true, workingDirectory, Buf);
|
||||||
workingDirectory, Buf);
|
|
||||||
|
|
||||||
Output->setAdditionalOutputForType(file_types::TY_OptRecord, filename);
|
Output->setAdditionalOutputForType(*FileType, filename);
|
||||||
} else
|
} else
|
||||||
// FIXME: We should use the OutputMap in this case.
|
// FIXME: We should use the OutputMap in this case.
|
||||||
Diags.diagnose({}, diag::warn_opt_remark_disabled);
|
Diags.diagnose({}, diag::warn_opt_remark_disabled);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/Option/ArgList.h"
|
#include "llvm/Option/ArgList.h"
|
||||||
|
#include "llvm/Remarks/RemarkFormat.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/Program.h"
|
#include "llvm/Support/Program.h"
|
||||||
@@ -340,3 +341,25 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
|
|||||||
std::move(invocationInfo.FilelistInfos), sortedJobs, NextQuasiPID,
|
std::move(invocationInfo.FilelistInfos), sortedJobs, NextQuasiPID,
|
||||||
responseFileInfo);
|
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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -423,8 +423,29 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
|||||||
Arguments.push_back("-cross-module-optimization");
|
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)) {
|
if (context.Args.hasArg(options::OPT_migrate_keep_objc_visibility)) {
|
||||||
Arguments.push_back("-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_CompiledSource:
|
||||||
case file_types::TY_ModuleTrace:
|
case file_types::TY_ModuleTrace:
|
||||||
case file_types::TY_TBD:
|
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_SwiftModuleInterfaceFile:
|
||||||
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
||||||
case file_types::TY_SwiftSourceInfoFile:
|
case file_types::TY_SwiftSourceInfoFile:
|
||||||
@@ -815,7 +837,8 @@ ToolChain::constructInvocation(const BackendJobAction &job,
|
|||||||
case file_types::TY_CompiledSource:
|
case file_types::TY_CompiledSource:
|
||||||
case file_types::TY_Remapping:
|
case file_types::TY_Remapping:
|
||||||
case file_types::TY_ModuleTrace:
|
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_SwiftModuleInterfaceFile:
|
||||||
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
case file_types::TY_PrivateSwiftModuleInterfaceFile:
|
||||||
case file_types::TY_SwiftSourceInfoFile:
|
case file_types::TY_SwiftSourceInfoFile:
|
||||||
|
|||||||
@@ -999,6 +999,20 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
|
|||||||
Opts.EnableDynamicReplacementCanCallPreviousImplementation = !Args.hasArg(
|
Opts.EnableDynamicReplacementCanCallPreviousImplementation = !Args.hasArg(
|
||||||
OPT_disable_previous_implementation_calls_in_dynamic_replacements);
|
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))
|
if (const Arg *A = Args.getLastArg(OPT_save_optimization_record_path))
|
||||||
Opts.OptRecordFile = A->getValue();
|
Opts.OptRecordFile = A->getValue();
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
#include "swift/Serialization/SerializationOptions.h"
|
#include "swift/Serialization/SerializationOptions.h"
|
||||||
#include "swift/Serialization/SerializedModuleLoader.h"
|
#include "swift/Serialization/SerializedModuleLoader.h"
|
||||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||||
|
#include "swift/SIL/SILRemarkStreamer.h"
|
||||||
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
|
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
|
||||||
#include "swift/Syntax/SyntaxNodes.h"
|
#include "swift/Syntax/SyntaxNodes.h"
|
||||||
#include "swift/TBDGen/TBDGen.h"
|
#include "swift/TBDGen/TBDGen.h"
|
||||||
@@ -75,6 +76,8 @@
|
|||||||
#include "llvm/IRReader/IRReader.h"
|
#include "llvm/IRReader/IRReader.h"
|
||||||
#include "llvm/Option/Option.h"
|
#include "llvm/Option/Option.h"
|
||||||
#include "llvm/Option/OptTable.h"
|
#include "llvm/Option/OptTable.h"
|
||||||
|
#include "llvm/Remarks/RemarkSerializer.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@@ -708,21 +711,6 @@ static void countStatsPostSILGen(UnifiedStatsReporter &Stats,
|
|||||||
C.NumSILGenGlobalVariables += Module.getSILGlobalList().size();
|
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,
|
static bool precompileBridgingHeader(const CompilerInvocation &Invocation,
|
||||||
const CompilerInstance &Instance) {
|
const CompilerInstance &Instance) {
|
||||||
auto clangImporter = static_cast<ClangImporter *>(
|
auto clangImporter = static_cast<ClangImporter *>(
|
||||||
@@ -1532,14 +1520,10 @@ static bool performCompileStepsPostSILGen(
|
|||||||
return Context.hadError();
|
return Context.hadError();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<llvm::raw_fd_ostream> OptRecordFile =
|
auto pair = createSILRemarkStreamer(
|
||||||
createOptRecordFile(SILOpts.OptRecordFile, Instance.getDiags());
|
*SM, SILOpts.OptRecordFile, SILOpts.OptRecordPasses,
|
||||||
if (OptRecordFile) {
|
SILOpts.OptRecordFormat, Instance.getDiags(), Instance.getSourceMgr());
|
||||||
auto Output =
|
SM->setSILRemarkStreamer(std::move(pair.first), std::move(pair.second));
|
||||||
std::make_unique<llvm::yaml::Output>(*OptRecordFile,
|
|
||||||
&Instance.getSourceMgr());
|
|
||||||
SM->setOptRecordStream(std::move(Output), std::move(OptRecordFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the action to be used to serialize SILModule.
|
// This is the action to be used to serialize SILModule.
|
||||||
// It may be invoked multiple times, but it will perform
|
// It may be invoked multiple times, but it will perform
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ add_swift_host_library(swiftSIL STATIC
|
|||||||
SILOpenedArchetypesTracker.cpp
|
SILOpenedArchetypesTracker.cpp
|
||||||
SILPrinter.cpp
|
SILPrinter.cpp
|
||||||
SILProfiler.cpp
|
SILProfiler.cpp
|
||||||
|
SILRemarkStreamer.cpp
|
||||||
SILSuccessor.cpp
|
SILSuccessor.cpp
|
||||||
SILType.cpp
|
SILType.cpp
|
||||||
SILUndef.cpp
|
SILUndef.cpp
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "swift/AST/DiagnosticEngine.h"
|
#include "swift/AST/DiagnosticEngine.h"
|
||||||
#include "swift/AST/DiagnosticsSIL.h"
|
#include "swift/AST/DiagnosticsSIL.h"
|
||||||
#include "swift/Demangling/Demangler.h"
|
#include "swift/Demangling/Demangler.h"
|
||||||
|
#include "swift/SIL/SILRemarkStreamer.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/Support/YAMLTraits.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
@@ -105,9 +105,8 @@ static void emitRemark(SILModule &module, const Remark<RemarkT> &remark,
|
|||||||
Diag<ArgTypes...> id, bool diagEnabled) {
|
Diag<ArgTypes...> id, bool diagEnabled) {
|
||||||
if (remark.getLocation().isInvalid())
|
if (remark.getLocation().isInvalid())
|
||||||
return;
|
return;
|
||||||
if (auto *out = module.getOptRecordStream())
|
if (auto *remarkStreamer = module.getSILRemarkStreamer())
|
||||||
// YAMLTraits takes a non-const reference even when outputting.
|
remarkStreamer->emit(remark);
|
||||||
*out << const_cast<Remark<RemarkT> &>(remark);
|
|
||||||
if (diagEnabled)
|
if (diagEnabled)
|
||||||
module.getASTContext().Diags.diagnose(remark.getLocation(), id,
|
module.getASTContext().Diags.diagnose(remark.getLocation(), id,
|
||||||
remark.getMsg());
|
remark.getMsg());
|
||||||
@@ -130,66 +129,3 @@ void Emitter::emitDebug(const RemarkPassed &remark) {
|
|||||||
void Emitter::emitDebug(const RemarkMissed &remark) {
|
void Emitter::emitDebug(const RemarkMissed &remark) {
|
||||||
llvm::dbgs() << remark.getDebugMsg();
|
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)
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "swift/SIL/FormalLinkage.h"
|
#include "swift/SIL/FormalLinkage.h"
|
||||||
#include "swift/SIL/Notifications.h"
|
#include "swift/SIL/Notifications.h"
|
||||||
#include "swift/SIL/SILDebugScope.h"
|
#include "swift/SIL/SILDebugScope.h"
|
||||||
|
#include "swift/SIL/SILRemarkStreamer.h"
|
||||||
#include "swift/SIL/SILValue.h"
|
#include "swift/SIL/SILValue.h"
|
||||||
#include "swift/SIL/SILVisitor.h"
|
#include "swift/SIL/SILVisitor.h"
|
||||||
#include "swift/Serialization/SerializedSILLoader.h"
|
#include "swift/Serialization/SerializedSILLoader.h"
|
||||||
@@ -689,11 +690,11 @@ void SILModule::serialize() {
|
|||||||
setSerialized();
|
setSerialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SILModule::setOptRecordStream(
|
void SILModule::setSILRemarkStreamer(
|
||||||
std::unique_ptr<llvm::yaml::Output> &&Stream,
|
std::unique_ptr<llvm::raw_fd_ostream> &&remarkStream,
|
||||||
std::unique_ptr<llvm::raw_ostream> &&RawStream) {
|
std::unique_ptr<swift::SILRemarkStreamer> &&remarkStreamer) {
|
||||||
OptRecordStream = std::move(Stream);
|
silRemarkStream = std::move(remarkStream);
|
||||||
OptRecordRawStream = std::move(RawStream);
|
silRemarkStreamer = std::move(remarkStreamer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SILModule::isStdlibModule() const {
|
bool SILModule::isStdlibModule() const {
|
||||||
|
|||||||
63
lib/SIL/SILRemarkStreamer.cpp
Normal file
63
lib/SIL/SILRemarkStreamer.cpp
Normal 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)};
|
||||||
|
}
|
||||||
31
test/Driver/opt-record-bitstream.swift
Normal file
31
test/Driver/opt-record-bitstream.swift
Normal 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>
|
||||||
|
}
|
||||||
20
test/Driver/opt-record-options.swift
Normal file
20
test/Driver/opt-record-options.swift
Normal 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
|
||||||
@@ -3,12 +3,16 @@
|
|||||||
// RUN: %FileCheck -check-prefix=YAML %s < %t/optrecordmod.opt.yaml
|
// 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: %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: %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
|
// CHECK-NOT: remark
|
||||||
|
|
||||||
var a: Int = 1
|
var a: Int = 1
|
||||||
|
|
||||||
#sourceLocation(file: "custom.swuft", line: 2000)
|
#sourceLocation(file: "custom.swift", line: 2000)
|
||||||
func foo() {
|
func foo() {
|
||||||
a = 2
|
a = 2
|
||||||
}
|
}
|
||||||
@@ -20,22 +24,22 @@ public func bar() {
|
|||||||
// YAML-NEXT: Pass: sil-inliner
|
// YAML-NEXT: Pass: sil-inliner
|
||||||
// YAML-NEXT: Name: sil.Inlined
|
// YAML-NEXT: Name: sil.Inlined
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}opt-record.swift
|
// YAML: File: {{.*}}opt-record.swift
|
||||||
// YAML-NEXT: Line: [[@LINE-6]]
|
// YAML: Line: [[@LINE-6]]
|
||||||
// YAML-NEXT: Column: 3
|
// YAML: Column: 3
|
||||||
// YAML-NEXT: Function: 'bar()'
|
// YAML-NEXT: Function: 'bar()'
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - Callee: '"optrecordmod.foo()"'
|
// YAML-NEXT: - Callee: '"optrecordmod.foo()"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: custom.swuft
|
// YAML: File: custom.swift
|
||||||
// YAML-NEXT: Line: 2000
|
// YAML: Line: 2000
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: - String: ' inlined into '
|
// YAML-NEXT: - String: ' inlined into '
|
||||||
// YAML-NEXT: - Caller: '"optrecordmod.bar()"'
|
// YAML-NEXT: - Caller: '"optrecordmod.bar()"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}opt-record.swift
|
// YAML: File: {{.*}}opt-record.swift
|
||||||
// YAML-NEXT: Line: [[@LINE-20]]
|
// YAML: Line: [[@LINE-20]]
|
||||||
// YAML-NEXT: Column: 13
|
// YAML: Column: 13
|
||||||
// YAML-NEXT: - String: ' (cost = '
|
// YAML-NEXT: - String: ' (cost = '
|
||||||
// YAML-NEXT: - Cost: '{{.*}}'
|
// YAML-NEXT: - Cost: '{{.*}}'
|
||||||
// YAML-NEXT: - String: ', benefit = '
|
// YAML-NEXT: - String: ', benefit = '
|
||||||
@@ -43,3 +47,5 @@ public func bar() {
|
|||||||
// YAML-NEXT: - String: ')'
|
// YAML-NEXT: - String: ')'
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YAML-FILTERED-NOT: sil-inliner
|
||||||
|
|||||||
@@ -33,17 +33,17 @@ sil hidden_external [transparent] [thunk] @witness_thunk2 : $@convention(witness
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.WitnessMethodDevirtualized
|
// YAML-NEXT: Name: sil.WitnessMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirt_class_witness_method.sil
|
// YAML: File: {{.*}}/devirt_class_witness_method.sil
|
||||||
// YAML-NEXT: Line: 55
|
// YAML: Line: 55
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: caller
|
// YAML-NEXT: Function: caller
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to '
|
// YAML-NEXT: - String: 'Devirtualized call to '
|
||||||
// YAML-NEXT: - Method: '"witness_thunk"'
|
// YAML-NEXT: - Method: '"witness_thunk"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirt_class_witness_method.sil
|
// YAML: File: {{.*}}/devirt_class_witness_method.sil
|
||||||
// YAML-NEXT: Line: 19
|
// YAML: Line: 19
|
||||||
// YAML-NEXT: Column: 44
|
// YAML: Column: 44
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
sil hidden @caller : $@convention(thin) <T, U> (@owned C<T, U>) -> () {
|
sil hidden @caller : $@convention(thin) <T, U> (@owned C<T, U>) -> () {
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ class Sub7 : Base {
|
|||||||
// YAML: Pass: sil-speculative-devirtualizer
|
// YAML: Pass: sil-speculative-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.PartialSpecDevirt
|
// YAML-NEXT: Name: sil.PartialSpecDevirt
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirt_speculate.swift
|
// YAML: File: {{.*}}/devirt_speculate.swift
|
||||||
// YAML-NEXT: Line: 118
|
// YAML: Line: 118
|
||||||
// YAML-NEXT: Column: 5
|
// YAML: Column: 5
|
||||||
// YAML-NEXT: Function: 'testMaxNumSpeculativeTargets(_:)'
|
// YAML-NEXT: Function: 'testMaxNumSpeculativeTargets(_:)'
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Partially devirtualized call with run-time checks for '
|
// YAML-NEXT: - String: 'Partially devirtualized call with run-time checks for '
|
||||||
|
|||||||
@@ -24,17 +24,17 @@ sil_global @x : $Bar
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 47
|
// YAML: Line: 47
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: function_with_cm
|
// YAML-NEXT: Function: function_with_cm
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
|
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 53
|
// YAML: Line: 53
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
sil @function_with_cm : $@convention(thin) () -> () {
|
sil @function_with_cm : $@convention(thin) () -> () {
|
||||||
@@ -82,17 +82,17 @@ bb0(%0 : $Node):
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 74
|
// YAML: Line: 74
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: class_method_apply
|
// YAML-NEXT: Function: class_method_apply
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"transparent_target"'
|
// YAML-NEXT: - Method: '"transparent_target"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 100
|
// YAML: Line: 100
|
||||||
// YAML-NEXT: Column: 39
|
// YAML: Column: 39
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
|
|
||||||
@@ -134,17 +134,17 @@ bb0(%0 : $@thick C.Type):
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 127
|
// YAML: Line: 127
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: 'caller(_:)'
|
// YAML-NEXT: Function: 'caller(_:)'
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
|
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize.sil
|
// YAML: File: {{.*}}/devirtualize.sil
|
||||||
// YAML-NEXT: Line: 118
|
// YAML: Line: 118
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
sil_vtable B {
|
sil_vtable B {
|
||||||
|
|||||||
@@ -25,17 +25,17 @@ sil_global @x : $Bar
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 46
|
// YAML: Line: 46
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: function_with_cm
|
// YAML-NEXT: Function: function_with_cm
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
|
// YAML-NEXT: - Method: '"main.Bar.foo(_:)"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 52
|
// YAML: Line: 52
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
sil [ossa] @function_with_cm : $@convention(thin) () -> () {
|
sil [ossa] @function_with_cm : $@convention(thin) () -> () {
|
||||||
@@ -83,17 +83,17 @@ bb0(%0 : @guaranteed $Node):
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 75
|
// YAML: Line: 75
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: class_method_apply
|
// YAML-NEXT: Function: class_method_apply
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"transparent_target"'
|
// YAML-NEXT: - Method: '"transparent_target"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 101
|
// YAML: Line: 101
|
||||||
// YAML-NEXT: Column: 46
|
// YAML: Column: 46
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
|
|
||||||
@@ -135,17 +135,17 @@ bb0(%0 : $@thick C.Type):
|
|||||||
// YAML-NEXT: Pass: sil-devirtualizer
|
// YAML-NEXT: Pass: sil-devirtualizer
|
||||||
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
// YAML-NEXT: Name: sil.ClassMethodDevirtualized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 128
|
// YAML: Line: 128
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: 'caller(_:)'
|
// YAML-NEXT: Function: 'caller(_:)'
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
// YAML-NEXT: - String: 'Devirtualized call to class method '
|
||||||
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
|
// YAML-NEXT: - Method: '"static meta.B.foo(_:)"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/devirtualize_ownership.sil
|
// YAML: File: {{.*}}/devirtualize_ownership.sil
|
||||||
// YAML-NEXT: Line: 119
|
// YAML: Line: 119
|
||||||
// YAML-NEXT: Column: 13
|
// YAML: Column: 13
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|
||||||
sil_vtable B {
|
sil_vtable B {
|
||||||
|
|||||||
@@ -198,22 +198,22 @@ bb0:
|
|||||||
// YAML-NEXT: Pass: sil-inliner
|
// YAML-NEXT: Pass: sil-inliner
|
||||||
// YAML-NEXT: Name: sil.Inlined
|
// YAML-NEXT: Name: sil.Inlined
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
|
// YAML: File: {{.*}}inliner_coldblocks.sil
|
||||||
// YAML-NEXT: Line: 223
|
// YAML: Line: 223
|
||||||
// YAML-NEXT: Column: 3
|
// YAML: Column: 3
|
||||||
// YAML-NEXT: Function: regular_large_callee
|
// YAML-NEXT: Function: regular_large_callee
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - Callee: '"update_global"'
|
// YAML-NEXT: - Callee: '"update_global"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
|
// YAML: File: {{.*}}inliner_coldblocks.sil
|
||||||
// YAML-NEXT: Line: 20
|
// YAML: Line: 20
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: - String: ' inlined into '
|
// YAML-NEXT: - String: ' inlined into '
|
||||||
// YAML-NEXT: - Caller: '"regular_large_callee"'
|
// YAML-NEXT: - Caller: '"regular_large_callee"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
|
// YAML: File: {{.*}}inliner_coldblocks.sil
|
||||||
// YAML-NEXT: Line: 162
|
// YAML: Line: 162
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: - String: ' (cost = '
|
// YAML-NEXT: - String: ' (cost = '
|
||||||
// YAML-NEXT: - Cost: '{{.*}}'
|
// YAML-NEXT: - Cost: '{{.*}}'
|
||||||
// YAML-NEXT: - String: ', benefit = '
|
// YAML-NEXT: - String: ', benefit = '
|
||||||
@@ -238,17 +238,17 @@ bb0:
|
|||||||
// YAML-NEXT: Pass: sil-inliner
|
// YAML-NEXT: Pass: sil-inliner
|
||||||
// YAML-NEXT: Name: sil.NoInlinedCost
|
// YAML-NEXT: Name: sil.NoInlinedCost
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
|
// YAML: File: {{.*}}inliner_coldblocks.sil
|
||||||
// YAML-NEXT: Line: 258
|
// YAML: Line: 258
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: dont_inline_regular_large_callee
|
// YAML-NEXT: Function: dont_inline_regular_large_callee
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Not profitable to inline function '
|
// YAML-NEXT: - String: 'Not profitable to inline function '
|
||||||
// YAML-NEXT: - Callee: '"regular_large_callee"'
|
// YAML-NEXT: - Callee: '"regular_large_callee"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
|
// YAML: File: {{.*}}inliner_coldblocks.sil
|
||||||
// YAML-NEXT: Line: 162
|
// YAML: Line: 162
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: - String: ' (cost = '
|
// YAML-NEXT: - String: ' (cost = '
|
||||||
// YAML-NEXT: - Cost: '{{.*}}'
|
// YAML-NEXT: - Cost: '{{.*}}'
|
||||||
// YAML-NEXT: - String: ', benefit = '
|
// YAML-NEXT: - String: ', benefit = '
|
||||||
|
|||||||
@@ -23,17 +23,17 @@ import Swift
|
|||||||
// YAML-NEXT: Pass: sil-generic-specializer
|
// YAML-NEXT: Pass: sil-generic-specializer
|
||||||
// YAML-NEXT: Name: sil.Specialized
|
// YAML-NEXT: Name: sil.Specialized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/specialize.sil
|
// YAML: File: {{.*}}/specialize.sil
|
||||||
// YAML-NEXT: Line: 132
|
// YAML: Line: 132
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: exp1
|
// YAML-NEXT: Function: exp1
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Specialized function '
|
// YAML-NEXT: - String: 'Specialized function '
|
||||||
// YAML-NEXT: - Function: '"XXX_init"'
|
// YAML-NEXT: - Function: '"XXX_init"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/specialize.sil
|
// YAML: File: {{.*}}/specialize.sil
|
||||||
// YAML-NEXT: Line: 73
|
// YAML: Line: 73
|
||||||
// YAML-NEXT: Column: 17
|
// YAML: Column: 17
|
||||||
// YAML-NEXT: - String: ' with type '
|
// YAML-NEXT: - String: ' with type '
|
||||||
// YAML-NEXT: - FuncType: '(Int32, @thin XXX<Int32>.Type) -> XXX<Int32>'
|
// YAML-NEXT: - FuncType: '(Int32, @thin XXX<Int32>.Type) -> XXX<Int32>'
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
@@ -41,17 +41,17 @@ import Swift
|
|||||||
// YAML-NEXT: Pass: sil-generic-specializer
|
// YAML-NEXT: Pass: sil-generic-specializer
|
||||||
// YAML-NEXT: Name: sil.Specialized
|
// YAML-NEXT: Name: sil.Specialized
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/specialize.sil
|
// YAML: File: {{.*}}/specialize.sil
|
||||||
// YAML-NEXT: Line: 142
|
// YAML: Line: 142
|
||||||
// YAML-NEXT: Column: 9
|
// YAML: Column: 9
|
||||||
// YAML-NEXT: Function: exp1
|
// YAML-NEXT: Function: exp1
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Specialized function '
|
// YAML-NEXT: - String: 'Specialized function '
|
||||||
// YAML-NEXT: - Function: '"XXX_foo"'
|
// YAML-NEXT: - Function: '"XXX_foo"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/specialize.sil
|
// YAML: File: {{.*}}/specialize.sil
|
||||||
// YAML-NEXT: Line: 90
|
// YAML: Line: 90
|
||||||
// YAML-NEXT: Column: 17
|
// YAML: Column: 17
|
||||||
// YAML-NEXT: - String: ' with type '
|
// YAML-NEXT: - String: ' with type '
|
||||||
// YAML-NEXT: - FuncType: '(Int32, @inout XXX<Int32>) -> Int32'
|
// YAML-NEXT: - FuncType: '(Int32, @inout XXX<Int32>) -> Int32'
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
@@ -283,15 +283,15 @@ bb0(%0 : $Base):
|
|||||||
// CHECK: return %0 : $Base
|
// CHECK: return %0 : $Base
|
||||||
|
|
||||||
// YAML: Line: 277
|
// YAML: Line: 277
|
||||||
// YAML-NEXT: Column: 8
|
// YAML: Column: 8
|
||||||
// YAML-NEXT: Function: specialize_generic_upcast
|
// YAML-NEXT: Function: specialize_generic_upcast
|
||||||
// YAML-NEXT: Args:
|
// YAML-NEXT: Args:
|
||||||
// YAML-NEXT: - String: 'Specialized function '
|
// YAML-NEXT: - String: 'Specialized function '
|
||||||
// YAML-NEXT: - Function: '"generic_upcast"'
|
// YAML-NEXT: - Function: '"generic_upcast"'
|
||||||
// YAML-NEXT: DebugLoc:
|
// YAML-NEXT: DebugLoc:
|
||||||
// YAML-NEXT: File: {{.*}}/specialize.sil
|
// YAML: File: {{.*}}/specialize.sil
|
||||||
// YAML-NEXT: Line: 268
|
// YAML: Line: 268
|
||||||
// YAML-NEXT: Column: 6
|
// YAML: Column: 6
|
||||||
// YAML-NEXT: - String: ' with type '
|
// YAML-NEXT: - String: ' with type '
|
||||||
// YAML-NEXT: - FuncType: '(@owned Base) -> @owned Base'
|
// YAML-NEXT: - FuncType: '(@owned Base) -> @owned Base'
|
||||||
// YAML-NEXT: ...
|
// YAML-NEXT: ...
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ sil_stage canonical
|
|||||||
// CHECK-NEXT: Pass: sil-generic-specializer
|
// CHECK-NEXT: Pass: sil-generic-specializer
|
||||||
// CHECK-NEXT: Name: sil.NoDef
|
// CHECK-NEXT: Name: sil.NoDef
|
||||||
// CHECK-NEXT: DebugLoc:
|
// CHECK-NEXT: DebugLoc:
|
||||||
// CHECK-NEXT: File: {{.*}}/specialize_no_definition.sil
|
// CHECK: File: {{.*}}/specialize_no_definition.sil
|
||||||
// CHECK-NEXT: Line: 36
|
// CHECK: Line: 36
|
||||||
// CHECK-NEXT: Column: 8
|
// CHECK: Column: 8
|
||||||
// CHECK-NEXT: Function: foo
|
// CHECK-NEXT: Function: foo
|
||||||
// CHECK-NEXT: Args:
|
// CHECK-NEXT: Args:
|
||||||
// CHECK-NEXT: - String: 'Unable to specialize generic function '
|
// CHECK-NEXT: - String: 'Unable to specialize generic function '
|
||||||
// CHECK-NEXT: - Callee: '"bar"'
|
// CHECK-NEXT: - Callee: '"bar"'
|
||||||
// CHECK-NEXT: DebugLoc:
|
// CHECK-NEXT: DebugLoc:
|
||||||
// CHECK-NEXT: File: {{.*}}/specialize_no_definition.sil
|
// CHECK: File: {{.*}}/specialize_no_definition.sil
|
||||||
// CHECK-NEXT: Line: 35
|
// CHECK: Line: 35
|
||||||
// CHECK-NEXT: Column: 21
|
// CHECK: Column: 21
|
||||||
// CHECK-NEXT: - String: ' since definition is not visible'
|
// CHECK-NEXT: - String: ' since definition is not visible'
|
||||||
// CHECK-NEXT: ...
|
// CHECK-NEXT: ...
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "swift/Frontend/DiagnosticVerifier.h"
|
#include "swift/Frontend/DiagnosticVerifier.h"
|
||||||
#include "swift/Frontend/Frontend.h"
|
#include "swift/Frontend/Frontend.h"
|
||||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||||
|
#include "swift/SIL/SILRemarkStreamer.h"
|
||||||
#include "swift/SILOptimizer/Analysis/Analysis.h"
|
#include "swift/SILOptimizer/Analysis/Analysis.h"
|
||||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||||
#include "swift/SILOptimizer/PassManager/PassManager.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::desc("YAML output filename for pass remarks"),
|
||||||
cl::value_desc("filename"));
|
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,
|
static void runCommandLineSelectedPasses(SILModule *Module,
|
||||||
irgen::IRGenModule *IRGenMod) {
|
irgen::IRGenModule *IRGenMod) {
|
||||||
SILPassManager PM(Module, IRGenMod);
|
SILPassManager PM(Module, IRGenMod);
|
||||||
@@ -402,7 +417,8 @@ int main(int argc, char **argv) {
|
|||||||
CI.performSema();
|
CI.performSema();
|
||||||
|
|
||||||
// If parsing produced an error, don't run any passes.
|
// If parsing produced an error, don't run any passes.
|
||||||
if (CI.getASTContext().hadError())
|
bool HadError = CI.getASTContext().hadError();
|
||||||
|
if (HadError)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Load the SIL if we have a module. We have to do this after SILParse
|
// 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())
|
if (CI.getSILModule())
|
||||||
CI.getSILModule()->setSerializeSILAction([]{});
|
CI.getSILModule()->setSerializeSILAction([]{});
|
||||||
|
|
||||||
std::unique_ptr<llvm::raw_fd_ostream> OptRecordFile;
|
|
||||||
if (RemarksFilename != "") {
|
if (RemarksFilename != "") {
|
||||||
std::error_code EC;
|
llvm::remarks::Format remarksFormat = llvm::remarks::Format::YAML;
|
||||||
OptRecordFile = std::make_unique<llvm::raw_fd_ostream>(
|
llvm::Expected<llvm::remarks::Format> formatOrErr =
|
||||||
RemarksFilename, EC, llvm::sys::fs::F_None);
|
llvm::remarks::parseFormat(RemarksFormat);
|
||||||
if (EC) {
|
if (llvm::Error E = formatOrErr.takeError()) {
|
||||||
llvm::errs() << EC.message() << '\n';
|
CI.getDiags().diagnose(SourceLoc(),
|
||||||
return 1;
|
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());
|
auto Pair = createSILRemarkStreamer(*CI.getSILModule(), RemarksFilename,
|
||||||
CI.getSILModule()->setOptRecordStream(std::move(Stream),
|
RemarksPasses, remarksFormat,
|
||||||
std::move(OptRecordFile));
|
CI.getDiags(), CI.getSourceMgr());
|
||||||
|
CI.getSILModule()->setSILRemarkStreamer(std::move(Pair.first),
|
||||||
|
std::move(Pair.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OptimizationGroup == OptGroup::Diagnostics) {
|
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
|
// If we're in -verify mode, we've buffered up all of the generated
|
||||||
// diagnostics. Check now to ensure that they meet our expectations.
|
// diagnostics. Check now to ensure that they meet our expectations.
|
||||||
|
|||||||
Reference in New Issue
Block a user