mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
194 lines
6.0 KiB
C++
194 lines
6.0 KiB
C++
//===--- OptimizationRemark.cpp - Optimization diagnostics ------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// This file defines the remark type and the emitter class that passes can use
|
|
/// to emit optimization diagnostics.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/OptimizationRemark.h"
|
|
#include "swift/AST/DiagnosticEngine.h"
|
|
#include "swift/AST/DiagnosticsSIL.h"
|
|
#include "swift/Demangling/Demangler.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/Support/YAMLTraits.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace swift;
|
|
using namespace OptRemark;
|
|
|
|
Argument::Argument(StringRef Key, int N) : Key(Key), Val(llvm::itostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, long N) : Key(Key), Val(llvm::itostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, long long N)
|
|
: Key(Key), Val(llvm::itostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, unsigned N)
|
|
: Key(Key), Val(llvm::utostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, unsigned long N)
|
|
: Key(Key), Val(llvm::utostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, unsigned long long N)
|
|
: Key(Key), Val(llvm::utostr(N)) {}
|
|
|
|
Argument::Argument(StringRef Key, SILFunction *F)
|
|
: Key(Key) {
|
|
auto DO = Demangle::DemangleOptions::SimplifiedUIDemangleOptions();
|
|
// Enable module names so that we have a way of filtering out
|
|
// stdlib-related remarks.
|
|
DO.DisplayModuleNames = true;
|
|
|
|
Val = (Twine("\"") + Demangle::demangleSymbolAsString(F->getName(), DO) +
|
|
"\"")
|
|
.str();
|
|
|
|
if (F->hasLocation())
|
|
Loc = F->getLocation().getSourceLoc();
|
|
}
|
|
|
|
Argument::Argument(StringRef Key, SILType Ty) : Key(Key) {
|
|
llvm::raw_string_ostream OS(Val);
|
|
Ty.print(OS);
|
|
}
|
|
|
|
Argument::Argument(StringRef Key, CanType Ty) : Key(Key) {
|
|
llvm::raw_string_ostream OS(Val);
|
|
Ty.print(OS);
|
|
}
|
|
|
|
template <typename DerivedT> std::string Remark<DerivedT>::getMsg() const {
|
|
std::string Str;
|
|
llvm::raw_string_ostream OS(Str);
|
|
for (const Argument &Arg : Args)
|
|
OS << Arg.Val;
|
|
return OS.str();
|
|
}
|
|
|
|
template <typename DerivedT> std::string Remark<DerivedT>::getDebugMsg() const {
|
|
std::string Str;
|
|
llvm::raw_string_ostream OS(Str);
|
|
|
|
if (IndentDebugWidth)
|
|
OS << std::string(" ", IndentDebugWidth);
|
|
|
|
for (const Argument &Arg : Args)
|
|
OS << Arg.Val;
|
|
|
|
OS << "\n";
|
|
return OS.str();
|
|
}
|
|
|
|
Emitter::Emitter(StringRef PassName, SILModule &M)
|
|
: Module(M), PassName(PassName),
|
|
PassedEnabled(
|
|
M.getASTContext().LangOpts.OptimizationRemarkPassedPattern &&
|
|
M.getASTContext().LangOpts.OptimizationRemarkPassedPattern->match(
|
|
PassName)),
|
|
MissedEnabled(
|
|
M.getASTContext().LangOpts.OptimizationRemarkMissedPattern &&
|
|
M.getASTContext().LangOpts.OptimizationRemarkMissedPattern->match(
|
|
PassName)) {}
|
|
|
|
template <typename RemarkT, typename... ArgTypes>
|
|
static void emitRemark(SILModule &Module, const Remark<RemarkT> &R,
|
|
Diag<ArgTypes...> ID, bool DiagEnabled) {
|
|
if (R.getLocation().isInvalid())
|
|
return;
|
|
if (auto *Out = Module.getOptRecordStream())
|
|
// YAMLTraits takes a non-const reference even when outputting.
|
|
*Out << const_cast<Remark<RemarkT> &>(R);
|
|
if (DiagEnabled)
|
|
Module.getASTContext().Diags.diagnose(R.getLocation(), ID, R.getMsg());
|
|
}
|
|
|
|
void Emitter::emit(const RemarkPassed &R) {
|
|
emitRemark(Module, R, diag::opt_remark_passed, isEnabled<RemarkPassed>());
|
|
}
|
|
|
|
void Emitter::emit(const RemarkMissed &R) {
|
|
emitRemark(Module, R, diag::opt_remark_missed, isEnabled<RemarkMissed>());
|
|
}
|
|
|
|
void Emitter::emitDebug(const RemarkPassed &R) {
|
|
llvm::dbgs() << R.getDebugMsg();
|
|
}
|
|
|
|
void Emitter::emitDebug(const RemarkMissed &R) {
|
|
llvm::dbgs() << R.getDebugMsg();
|
|
}
|
|
|
|
namespace llvm {
|
|
namespace yaml {
|
|
|
|
template <typename KindT> struct MappingTraits<Remark<KindT>> {
|
|
static void mapping(llvm::yaml::IO &io, Remark<KindT> &R) {
|
|
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 = R.getPassName();
|
|
io.mapRequired("Pass", PassName);
|
|
std::string Id = (Twine("sil.") + R.getIdentifier()).str();
|
|
io.mapRequired("Name", Id);
|
|
|
|
SourceLoc Loc = R.getLocation();
|
|
if (!io.outputting() || Loc.isValid())
|
|
io.mapOptional("DebugLoc", Loc);
|
|
|
|
std::string FN = Demangle::demangleSymbolAsString(
|
|
R.getFunction()->getName(),
|
|
Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
|
|
io.mapRequired("Function", FN);
|
|
io.mapOptional("Args", R.getArgs());
|
|
}
|
|
};
|
|
|
|
template <> struct MappingTraits<SourceLoc> {
|
|
static void mapping(IO &io, SourceLoc &Loc) {
|
|
assert(io.outputting() && "input not yet implemented");
|
|
|
|
SourceManager *SM = static_cast<SourceManager *>(io.getContext());
|
|
StringRef File = SM->getDisplayNameForLoc(Loc);
|
|
unsigned Line, Col;
|
|
std::tie(Line, Col) = SM->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)
|