mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #76662 from slavapestov/fine-grained-timers-flag
Add -fine-grained-timers flag
This commit is contained in:
@@ -167,6 +167,10 @@ private:
|
||||
std::unique_ptr<StatsProfilers> EventProfilers;
|
||||
std::unique_ptr<StatsProfilers> EntityProfilers;
|
||||
|
||||
/// Whether fine-grained timers are enabled. In practice, this means request
|
||||
/// evaluator requests. This will have a runtime performance impact.
|
||||
bool FineGrainedTimers;
|
||||
|
||||
/// Whether we are currently flushing statistics and should not therefore
|
||||
/// record any additional stats until we've finished.
|
||||
bool IsFlushingTracesAndProfiles;
|
||||
@@ -179,6 +183,7 @@ private:
|
||||
StringRef Directory,
|
||||
SourceManager *SM,
|
||||
clang::SourceManager *CSM,
|
||||
bool FineGrainedTimers,
|
||||
bool TraceEvents,
|
||||
bool ProfileEvents,
|
||||
bool ProfileEntities);
|
||||
@@ -190,13 +195,16 @@ public:
|
||||
StringRef OutputType,
|
||||
StringRef OptType,
|
||||
StringRef Directory,
|
||||
SourceManager *SM=nullptr,
|
||||
clang::SourceManager *CSM=nullptr,
|
||||
bool TraceEvents=false,
|
||||
bool ProfileEvents=false,
|
||||
bool ProfileEntities=false);
|
||||
SourceManager *SM,
|
||||
clang::SourceManager *CSM,
|
||||
bool FineGrainedTimers,
|
||||
bool TraceEvents,
|
||||
bool ProfileEvents,
|
||||
bool ProfileEntities);
|
||||
~UnifiedStatsReporter();
|
||||
|
||||
bool fineGrainedTimers() const { return FineGrainedTimers; }
|
||||
|
||||
AlwaysOnDriverCounters &getDriverCounters();
|
||||
AlwaysOnFrontendCounters &getFrontendCounters();
|
||||
void flushTracesAndProfiles();
|
||||
|
||||
@@ -228,6 +228,10 @@ public:
|
||||
/// The path to which we should output statistics files.
|
||||
std::string StatsOutputDir;
|
||||
|
||||
/// Whether to enable timers tracking individual requests. This adds some
|
||||
/// runtime overhead.
|
||||
bool FineGrainedTimers = false;
|
||||
|
||||
/// Trace changes to stats to files in StatsOutputDir.
|
||||
bool TraceStats = false;
|
||||
|
||||
|
||||
@@ -361,6 +361,9 @@ def driver_time_compilation : Flag<["-"], "driver-time-compilation">,
|
||||
def stats_output_dir: Separate<["-"], "stats-output-dir">,
|
||||
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
|
||||
HelpText<"Directory to write unified compilation-statistics files to">;
|
||||
def fine_grained_timers: Flag<["-"], "fine-grained-timers">,
|
||||
Flags<[FrontendOption, HelpHidden]>,
|
||||
HelpText<"Enable per-request timers">;
|
||||
def trace_stats_events: Flag<["-"], "trace-stats-events">,
|
||||
Flags<[FrontendOption, HelpHidden]>,
|
||||
HelpText<"Trace changes to stats in -stats-output-dir">;
|
||||
|
||||
@@ -928,12 +928,16 @@ swift::detail::ImportPathBuilder_getIdentifierImpl(ASTContext &ctx,
|
||||
|
||||
/// Set a new stats reporter.
|
||||
void ASTContext::setStatsReporter(UnifiedStatsReporter *stats) {
|
||||
if (stats) {
|
||||
stats->getFrontendCounters().NumASTBytesAllocated =
|
||||
getAllocator().getBytesAllocated();
|
||||
}
|
||||
evaluator.setStatsReporter(stats);
|
||||
if (!stats)
|
||||
return;
|
||||
|
||||
Stats = stats;
|
||||
|
||||
stats->getFrontendCounters().NumASTBytesAllocated =
|
||||
getAllocator().getBytesAllocated();
|
||||
|
||||
if (stats->fineGrainedTimers())
|
||||
evaluator.setStatsReporter(stats);
|
||||
}
|
||||
|
||||
/// getIdentifier - Return the uniqued and AST-Context-owned version of the
|
||||
|
||||
@@ -240,9 +240,6 @@ void UnqualifiedLookupFactory::performUnqualifiedLookup() {
|
||||
auto localCounter = lookupCounter;
|
||||
(void)localCounter; // for debugging
|
||||
#endif
|
||||
FrontendStatsTracer StatsTracer(Ctx.Stats,
|
||||
"performUnqualifiedLookup",
|
||||
DC->getParentSourceFile());
|
||||
|
||||
if (options.contains(UnqualifiedLookupFlags::ModuleLookup)) {
|
||||
lookForAModuleWithTheGivenName(DC->getModuleScopeContext());
|
||||
|
||||
@@ -319,6 +319,7 @@ UnifiedStatsReporter::UnifiedStatsReporter(StringRef ProgramName,
|
||||
StringRef Directory,
|
||||
SourceManager *SM,
|
||||
clang::SourceManager *CSM,
|
||||
bool FineGrainedTimers,
|
||||
bool TraceEvents,
|
||||
bool ProfileEvents,
|
||||
bool ProfileEntities)
|
||||
@@ -329,7 +330,7 @@ UnifiedStatsReporter::UnifiedStatsReporter(StringRef ProgramName,
|
||||
OutputType,
|
||||
OptType),
|
||||
Directory,
|
||||
SM, CSM,
|
||||
SM, CSM, FineGrainedTimers,
|
||||
TraceEvents, ProfileEvents, ProfileEntities)
|
||||
{
|
||||
}
|
||||
@@ -339,6 +340,7 @@ UnifiedStatsReporter::UnifiedStatsReporter(StringRef ProgramName,
|
||||
StringRef Directory,
|
||||
SourceManager *SM,
|
||||
clang::SourceManager *CSM,
|
||||
bool FineGrainedTimers,
|
||||
bool TraceEvents,
|
||||
bool ProfileEvents,
|
||||
bool ProfileEntities)
|
||||
@@ -355,7 +357,8 @@ UnifiedStatsReporter::UnifiedStatsReporter(StringRef ProgramName,
|
||||
SourceMgr(SM),
|
||||
ClangSourceMgr(CSM),
|
||||
RecursiveTimers(std::make_unique<RecursionSafeTimers>()),
|
||||
IsFlushingTracesAndProfiles(false)
|
||||
IsFlushingTracesAndProfiles(false),
|
||||
FineGrainedTimers(FineGrainedTimers)
|
||||
{
|
||||
path::append(StatsFilename, makeStatsFileName(ProgramName, AuxName));
|
||||
path::append(TraceFilename, makeTraceFileName(ProgramName, AuxName));
|
||||
@@ -453,20 +456,22 @@ UnifiedStatsReporter::printAlwaysOnStatsAndTimers(raw_ostream &OS) {
|
||||
const char *delim = "";
|
||||
if (FrontendCounters) {
|
||||
auto &C = getFrontendCounters();
|
||||
#define FRONTEND_STATISTIC(TY, NAME) \
|
||||
do { \
|
||||
OS << delim << "\t\"" #TY "." #NAME "\": " << C.NAME; \
|
||||
delim = ",\n"; \
|
||||
#define FRONTEND_STATISTIC(TY, NAME) \
|
||||
do { \
|
||||
if (C.NAME) \
|
||||
OS << delim << "\t\"" #TY "." #NAME "\": " << C.NAME; \
|
||||
delim = ",\n"; \
|
||||
} while (0);
|
||||
#include "swift/Basic/Statistics.def"
|
||||
#undef FRONTEND_STATISTIC
|
||||
}
|
||||
if (DriverCounters) {
|
||||
auto &C = getDriverCounters();
|
||||
#define DRIVER_STATISTIC(NAME) \
|
||||
do { \
|
||||
OS << delim << "\t\"Driver." #NAME "\": " << C.NAME; \
|
||||
delim = ",\n"; \
|
||||
#define DRIVER_STATISTIC(NAME) \
|
||||
do { \
|
||||
if (C.NAME) \
|
||||
OS << delim << "\t\"Driver." #NAME "\": " << C.NAME; \
|
||||
delim = ",\n"; \
|
||||
} while (0);
|
||||
#include "swift/Basic/Statistics.def"
|
||||
#undef DRIVER_STATISTIC
|
||||
|
||||
@@ -516,7 +516,13 @@ createStatsReporter(const llvm::opt::InputArgList *ArgList,
|
||||
DefaultTargetTriple,
|
||||
OutputType,
|
||||
OptType,
|
||||
A->getValue());
|
||||
A->getValue(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -416,6 +416,9 @@ void ArgsToFrontendOptionsConverter::computeDebugTimeOptions() {
|
||||
using namespace options;
|
||||
if (const Arg *A = Args.getLastArg(OPT_stats_output_dir)) {
|
||||
Opts.StatsOutputDir = A->getValue();
|
||||
if (Args.getLastArg(OPT_fine_grained_timers)) {
|
||||
Opts.FineGrainedTimers = true;
|
||||
}
|
||||
if (Args.getLastArg(OPT_trace_stats_events)) {
|
||||
Opts.TraceStats = true;
|
||||
}
|
||||
|
||||
@@ -381,6 +381,7 @@ void CompilerInstance::setupStatsReporter() {
|
||||
StatsOutputDir,
|
||||
&getSourceMgr(),
|
||||
getClangSourceManager(getASTContext()),
|
||||
Invoke.getFrontendOptions().FineGrainedTimers,
|
||||
Invoke.getFrontendOptions().TraceStats,
|
||||
Invoke.getFrontendOptions().ProfileEvents,
|
||||
Invoke.getFrontendOptions().ProfileEntities);
|
||||
|
||||
@@ -1450,123 +1450,127 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
|
||||
IGM->addLinkLibraries();
|
||||
IGMcreated = true;
|
||||
}
|
||||
|
||||
|
||||
if (!IGMcreated) {
|
||||
// TODO: Check this already at argument parsing.
|
||||
Ctx.Diags.diagnose(SourceLoc(), diag::no_input_files_for_mt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit the module contents.
|
||||
irgen.emitGlobalTopLevel(desc.getLinkerDirectives());
|
||||
{
|
||||
FrontendStatsTracer tracer(Ctx.Stats, "IRGen");
|
||||
|
||||
for (auto *File : M->getFiles()) {
|
||||
if (auto *SF = dyn_cast<SourceFile>(File)) {
|
||||
{
|
||||
CurrentIGMPtr IGM = irgen.getGenModule(SF);
|
||||
IGM->emitSourceFile(*SF);
|
||||
}
|
||||
|
||||
if (auto *synthSFU = File->getSynthesizedFile()) {
|
||||
CurrentIGMPtr IGM = irgen.getGenModule(synthSFU);
|
||||
IGM->emitSynthesizedFileUnit(*synthSFU);
|
||||
// Emit the module contents.
|
||||
irgen.emitGlobalTopLevel(desc.getLinkerDirectives());
|
||||
|
||||
for (auto *File : M->getFiles()) {
|
||||
if (auto *SF = dyn_cast<SourceFile>(File)) {
|
||||
{
|
||||
CurrentIGMPtr IGM = irgen.getGenModule(SF);
|
||||
IGM->emitSourceFile(*SF);
|
||||
}
|
||||
|
||||
if (auto *synthSFU = File->getSynthesizedFile()) {
|
||||
CurrentIGMPtr IGM = irgen.getGenModule(synthSFU);
|
||||
IGM->emitSynthesizedFileUnit(*synthSFU);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, emit any definitions that we suddenly need.
|
||||
irgen.emitLazyDefinitions();
|
||||
|
||||
irgen.emitSwiftProtocols();
|
||||
// Okay, emit any definitions that we suddenly need.
|
||||
irgen.emitLazyDefinitions();
|
||||
|
||||
irgen.emitDynamicReplacements();
|
||||
irgen.emitSwiftProtocols();
|
||||
|
||||
irgen.emitProtocolConformances();
|
||||
irgen.emitDynamicReplacements();
|
||||
|
||||
irgen.emitTypeMetadataRecords();
|
||||
irgen.emitProtocolConformances();
|
||||
|
||||
irgen.emitAccessibleFunctions();
|
||||
irgen.emitTypeMetadataRecords();
|
||||
|
||||
irgen.emitReflectionMetadataVersion();
|
||||
irgen.emitAccessibleFunctions();
|
||||
|
||||
irgen.emitEagerClassInitialization();
|
||||
irgen.emitObjCActorsNeedingSuperclassSwizzle();
|
||||
irgen.emitReflectionMetadataVersion();
|
||||
|
||||
// Emit reflection metadata for builtin and imported types.
|
||||
irgen.emitBuiltinReflectionMetadata();
|
||||
irgen.emitEagerClassInitialization();
|
||||
irgen.emitObjCActorsNeedingSuperclassSwizzle();
|
||||
|
||||
// Emit coverage mapping info. This needs to happen after we've emitted
|
||||
// any lazy definitions, as we need to know whether or not we emitted a
|
||||
// profiler increment for a given coverage map.
|
||||
irgen.emitCoverageMapping();
|
||||
// Emit reflection metadata for builtin and imported types.
|
||||
irgen.emitBuiltinReflectionMetadata();
|
||||
|
||||
IRGenModule *PrimaryGM = irgen.getPrimaryIGM();
|
||||
// Emit coverage mapping info. This needs to happen after we've emitted
|
||||
// any lazy definitions, as we need to know whether or not we emitted a
|
||||
// profiler increment for a given coverage map.
|
||||
irgen.emitCoverageMapping();
|
||||
|
||||
// Emit symbols for eliminated dead methods.
|
||||
PrimaryGM->emitVTableStubs();
|
||||
IRGenModule *PrimaryGM = irgen.getPrimaryIGM();
|
||||
|
||||
// Emit symbols for eliminated dead methods.
|
||||
PrimaryGM->emitVTableStubs();
|
||||
|
||||
// Verify type layout if we were asked to.
|
||||
if (!Opts.VerifyTypeLayoutNames.empty())
|
||||
PrimaryGM->emitTypeVerifier();
|
||||
|
||||
// Verify type layout if we were asked to.
|
||||
if (!Opts.VerifyTypeLayoutNames.empty())
|
||||
PrimaryGM->emitTypeVerifier();
|
||||
|
||||
std::for_each(Opts.LinkLibraries.begin(), Opts.LinkLibraries.end(),
|
||||
[&](LinkLibrary linkLib) {
|
||||
PrimaryGM->addLinkLibrary(linkLib);
|
||||
});
|
||||
|
||||
llvm::DenseSet<StringRef> referencedGlobals;
|
||||
std::for_each(Opts.LinkLibraries.begin(), Opts.LinkLibraries.end(),
|
||||
[&](LinkLibrary linkLib) {
|
||||
PrimaryGM->addLinkLibrary(linkLib);
|
||||
});
|
||||
|
||||
for (auto it = irgen.begin(); it != irgen.end(); ++it) {
|
||||
IRGenModule *IGM = it->second;
|
||||
llvm::Module *M = IGM->getModule();
|
||||
auto collectReference = [&](llvm::GlobalValue &G) {
|
||||
if (G.isDeclaration()
|
||||
&& (G.getLinkage() == GlobalValue::LinkOnceODRLinkage ||
|
||||
G.getLinkage() == GlobalValue::ExternalLinkage)) {
|
||||
referencedGlobals.insert(G.getName());
|
||||
G.setLinkage(GlobalValue::ExternalLinkage);
|
||||
llvm::DenseSet<StringRef> referencedGlobals;
|
||||
|
||||
for (auto it = irgen.begin(); it != irgen.end(); ++it) {
|
||||
IRGenModule *IGM = it->second;
|
||||
llvm::Module *M = IGM->getModule();
|
||||
auto collectReference = [&](llvm::GlobalValue &G) {
|
||||
if (G.isDeclaration()
|
||||
&& (G.getLinkage() == GlobalValue::LinkOnceODRLinkage ||
|
||||
G.getLinkage() == GlobalValue::ExternalLinkage)) {
|
||||
referencedGlobals.insert(G.getName());
|
||||
G.setLinkage(GlobalValue::ExternalLinkage);
|
||||
}
|
||||
};
|
||||
for (llvm::GlobalVariable &G : M->globals()) {
|
||||
collectReference(G);
|
||||
}
|
||||
};
|
||||
for (llvm::GlobalVariable &G : M->globals()) {
|
||||
collectReference(G);
|
||||
}
|
||||
for (llvm::Function &F : M->getFunctionList()) {
|
||||
collectReference(F);
|
||||
}
|
||||
for (llvm::GlobalAlias &A : M->aliases()) {
|
||||
collectReference(A);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = irgen.begin(); it != irgen.end(); ++it) {
|
||||
IRGenModule *IGM = it->second;
|
||||
llvm::Module *M = IGM->getModule();
|
||||
|
||||
// Update the linkage of shared functions/globals.
|
||||
// If a shared function/global is referenced from another file it must have
|
||||
// weak instead of linkonce linkage. Otherwise LLVM would remove the
|
||||
// definition (if it's not referenced in the same file).
|
||||
auto updateLinkage = [&](llvm::GlobalValue &G) {
|
||||
if (!G.isDeclaration()
|
||||
&& G.getLinkage() == GlobalValue::LinkOnceODRLinkage
|
||||
&& referencedGlobals.count(G.getName()) != 0) {
|
||||
G.setLinkage(GlobalValue::WeakODRLinkage);
|
||||
for (llvm::Function &F : M->getFunctionList()) {
|
||||
collectReference(F);
|
||||
}
|
||||
for (llvm::GlobalAlias &A : M->aliases()) {
|
||||
collectReference(A);
|
||||
}
|
||||
};
|
||||
for (llvm::GlobalVariable &G : M->globals()) {
|
||||
updateLinkage(G);
|
||||
}
|
||||
for (llvm::Function &F : M->getFunctionList()) {
|
||||
updateLinkage(F);
|
||||
}
|
||||
for (llvm::GlobalAlias &A : M->aliases()) {
|
||||
updateLinkage(A);
|
||||
}
|
||||
|
||||
if (!IGM->finalize())
|
||||
return;
|
||||
for (auto it = irgen.begin(); it != irgen.end(); ++it) {
|
||||
IRGenModule *IGM = it->second;
|
||||
llvm::Module *M = IGM->getModule();
|
||||
|
||||
setModuleFlags(*IGM);
|
||||
// Update the linkage of shared functions/globals.
|
||||
// If a shared function/global is referenced from another file it must have
|
||||
// weak instead of linkonce linkage. Otherwise LLVM would remove the
|
||||
// definition (if it's not referenced in the same file).
|
||||
auto updateLinkage = [&](llvm::GlobalValue &G) {
|
||||
if (!G.isDeclaration()
|
||||
&& G.getLinkage() == GlobalValue::LinkOnceODRLinkage
|
||||
&& referencedGlobals.count(G.getName()) != 0) {
|
||||
G.setLinkage(GlobalValue::WeakODRLinkage);
|
||||
}
|
||||
};
|
||||
for (llvm::GlobalVariable &G : M->globals()) {
|
||||
updateLinkage(G);
|
||||
}
|
||||
for (llvm::Function &F : M->getFunctionList()) {
|
||||
updateLinkage(F);
|
||||
}
|
||||
for (llvm::GlobalAlias &A : M->aliases()) {
|
||||
updateLinkage(A);
|
||||
}
|
||||
|
||||
if (!IGM->finalize())
|
||||
return;
|
||||
|
||||
setModuleFlags(*IGM);
|
||||
}
|
||||
}
|
||||
|
||||
// Bail out if there are any errors.
|
||||
|
||||
@@ -2016,134 +2016,93 @@ void SILGenModule::visitPoundDiagnosticDecl(PoundDiagnosticDecl *PDD) {
|
||||
// Nothing to do for #error/#warning; they've already been emitted.
|
||||
}
|
||||
|
||||
namespace {
|
||||
void SILGenModule::emitSourceFile(SourceFile *sf) {
|
||||
// Type-check the file if we haven't already.
|
||||
performTypeChecking(*sf);
|
||||
|
||||
// An RAII object that constructs a \c SILGenModule instance.
|
||||
// On destruction, delayed definitions are automatically emitted.
|
||||
class SILGenModuleRAII {
|
||||
SILGenModule SGM;
|
||||
if (sf->isScriptMode()) {
|
||||
emitEntryPoint(sf);
|
||||
}
|
||||
|
||||
public:
|
||||
void emitSourceFile(SourceFile *sf) {
|
||||
// Type-check the file if we haven't already.
|
||||
performTypeChecking(*sf);
|
||||
for (auto *D : sf->getTopLevelDecls()) {
|
||||
// Emit auxiliary decls.
|
||||
D->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) {
|
||||
visit(auxiliaryDecl);
|
||||
});
|
||||
|
||||
if (sf->isScriptMode()) {
|
||||
SGM.emitEntryPoint(sf);
|
||||
}
|
||||
visit(D);
|
||||
}
|
||||
|
||||
for (auto *D : sf->getTopLevelDecls()) {
|
||||
// Emit auxiliary decls.
|
||||
D->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) {
|
||||
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
|
||||
"SILgen-decl", auxiliaryDecl);
|
||||
SGM.visit(auxiliaryDecl);
|
||||
});
|
||||
|
||||
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
|
||||
"SILgen-decl", D);
|
||||
SGM.visit(D);
|
||||
}
|
||||
|
||||
// FIXME: Visit macro-generated extensions separately.
|
||||
//
|
||||
// The code below that visits auxiliary decls of the top-level
|
||||
// decls in the source file does not work for nested types with
|
||||
// attached conformance macros:
|
||||
// ```
|
||||
// struct Outer {
|
||||
// @AddConformance struct Inner {}
|
||||
// }
|
||||
// ```
|
||||
// Because the attached-to decl is not at the top-level. To fix this,
|
||||
// visit the macro-generated conformances that are recorded in the
|
||||
// synthesized file unit to cover all macro-generated extension decls.
|
||||
if (auto *synthesizedFile = sf->getSynthesizedFile()) {
|
||||
for (auto *D : synthesizedFile->getTopLevelDecls()) {
|
||||
if (!isa<ExtensionDecl>(D))
|
||||
continue;
|
||||
|
||||
auto *sf = D->getInnermostDeclContext()->getParentSourceFile();
|
||||
if (sf->getFulfilledMacroRole() != MacroRole::Conformance &&
|
||||
sf->getFulfilledMacroRole() != MacroRole::Extension)
|
||||
continue;
|
||||
|
||||
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
|
||||
"SILgen-decl", D);
|
||||
SGM.visit(D);
|
||||
}
|
||||
}
|
||||
|
||||
for (Decl *D : sf->getHoistedDecls()) {
|
||||
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
|
||||
"SILgen-decl", D);
|
||||
SGM.visit(D);
|
||||
}
|
||||
|
||||
for (TypeDecl *TD : sf->getLocalTypeDecls()) {
|
||||
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
|
||||
"SILgen-tydecl", TD);
|
||||
// FIXME: Delayed parsing would prevent these types from being added to
|
||||
// the module in the first place.
|
||||
if (TD->getDeclContext()->getInnermostSkippedFunctionContext())
|
||||
// FIXME: Visit macro-generated extensions separately.
|
||||
//
|
||||
// The code below that visits auxiliary decls of the top-level
|
||||
// decls in the source file does not work for nested types with
|
||||
// attached conformance macros:
|
||||
// ```
|
||||
// struct Outer {
|
||||
// @AddConformance struct Inner {}
|
||||
// }
|
||||
// ```
|
||||
// Because the attached-to decl is not at the top-level. To fix this,
|
||||
// visit the macro-generated conformances that are recorded in the
|
||||
// synthesized file unit to cover all macro-generated extension decls.
|
||||
if (auto *synthesizedFile = sf->getSynthesizedFile()) {
|
||||
for (auto *D : synthesizedFile->getTopLevelDecls()) {
|
||||
if (!isa<ExtensionDecl>(D))
|
||||
continue;
|
||||
SGM.visit(TD);
|
||||
}
|
||||
|
||||
// If the source file contains an artificial main, emit the implicit
|
||||
// top-level code.
|
||||
if (auto *mainDecl = sf->getMainDecl()) {
|
||||
if (isa<FuncDecl>(mainDecl) &&
|
||||
static_cast<FuncDecl *>(mainDecl)->hasAsync())
|
||||
emitSILFunctionDefinition(
|
||||
SILDeclRef::getAsyncMainDeclEntryPoint(mainDecl));
|
||||
emitSILFunctionDefinition(SILDeclRef::getMainDeclEntryPoint(mainDecl));
|
||||
auto *sf = D->getInnermostDeclContext()->getParentSourceFile();
|
||||
if (sf->getFulfilledMacroRole() != MacroRole::Conformance &&
|
||||
sf->getFulfilledMacroRole() != MacroRole::Extension)
|
||||
continue;
|
||||
|
||||
visit(D);
|
||||
}
|
||||
}
|
||||
|
||||
void emitSymbolSource(SymbolSource Source) {
|
||||
switch (Source.kind) {
|
||||
case SymbolSource::Kind::SIL:
|
||||
emitSILFunctionDefinition(Source.getSILDeclRef());
|
||||
break;
|
||||
case SymbolSource::Kind::Global:
|
||||
SGM.addGlobalVariable(Source.getGlobal());
|
||||
break;
|
||||
case SymbolSource::Kind::IR:
|
||||
llvm_unreachable("Unimplemented: Emission of LinkEntities");
|
||||
case SymbolSource::Kind::Unknown:
|
||||
case SymbolSource::Kind::LinkerDirective:
|
||||
// Nothing to do
|
||||
break;
|
||||
for (Decl *D : sf->getHoistedDecls()) {
|
||||
visit(D);
|
||||
}
|
||||
|
||||
for (TypeDecl *TD : sf->getLocalTypeDecls()) {
|
||||
// FIXME: Delayed parsing would prevent these types from being added to
|
||||
// the module in the first place.
|
||||
if (TD->getDeclContext()->getInnermostSkippedFunctionContext())
|
||||
continue;
|
||||
visit(TD);
|
||||
}
|
||||
|
||||
// If the source file contains an artificial main, emit the implicit
|
||||
// top-level code.
|
||||
if (auto *mainDecl = sf->getMainDecl()) {
|
||||
if (isa<FuncDecl>(mainDecl) &&
|
||||
static_cast<FuncDecl *>(mainDecl)->hasAsync()) {
|
||||
auto ref = SILDeclRef::getAsyncMainDeclEntryPoint(mainDecl);
|
||||
emitFunctionDefinition(ref, getFunction(ref, ForDefinition));
|
||||
}
|
||||
auto ref = SILDeclRef::getMainDeclEntryPoint(mainDecl);
|
||||
emitFunctionDefinition(ref, getFunction(ref, ForDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
void emitSILFunctionDefinition(SILDeclRef ref) {
|
||||
SGM.emitFunctionDefinition(ref, SGM.getFunction(ref, ForDefinition));
|
||||
void SILGenModule::emitSymbolSource(SymbolSource Source) {
|
||||
switch (Source.kind) {
|
||||
case SymbolSource::Kind::SIL: {
|
||||
auto ref = Source.getSILDeclRef();
|
||||
emitFunctionDefinition(ref, getFunction(ref, ForDefinition));
|
||||
break;
|
||||
}
|
||||
|
||||
explicit SILGenModuleRAII(SILModule &M) : SGM{M, M.getSwiftModule()} {}
|
||||
|
||||
~SILGenModuleRAII() {
|
||||
// Emit any delayed definitions that were forced.
|
||||
// Emitting these may in turn force more definitions, so we have to take
|
||||
// care to keep pumping the queues.
|
||||
while (!SGM.pendingForcedFunctions.empty()
|
||||
|| !SGM.pendingConformances.empty()) {
|
||||
while (!SGM.pendingForcedFunctions.empty()) {
|
||||
auto &front = SGM.pendingForcedFunctions.front();
|
||||
SGM.emitFunctionDefinition(
|
||||
front, SGM.getEmittedFunction(front, ForDefinition));
|
||||
SGM.pendingForcedFunctions.pop_front();
|
||||
}
|
||||
while (!SGM.pendingConformances.empty()) {
|
||||
(void)SGM.getWitnessTable(SGM.pendingConformances.front());
|
||||
SGM.pendingConformances.pop_front();
|
||||
}
|
||||
}
|
||||
case SymbolSource::Kind::Global:
|
||||
addGlobalVariable(Source.getGlobal());
|
||||
break;
|
||||
case SymbolSource::Kind::IR:
|
||||
llvm_unreachable("Unimplemented: Emission of LinkEntities");
|
||||
case SymbolSource::Kind::Unknown:
|
||||
case SymbolSource::Kind::LinkerDirective:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
}
|
||||
|
||||
std::unique_ptr<SILModule>
|
||||
ASTLoweringRequest::evaluate(Evaluator &evaluator,
|
||||
@@ -2156,28 +2115,31 @@ ASTLoweringRequest::evaluate(Evaluator &evaluator,
|
||||
auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
|
||||
desc.opts, desc.irgenOptions);
|
||||
|
||||
auto &ctx = silMod->getASTContext();
|
||||
FrontendStatsTracer tracer(ctx.Stats, "SILGen");
|
||||
|
||||
// If all function bodies are being skipped there's no reason to do any
|
||||
// SIL generation.
|
||||
if (desc.opts.SkipFunctionBodies == FunctionBodySkipping::All)
|
||||
return silMod;
|
||||
|
||||
// Skip emitting SIL if there's been any compilation errors
|
||||
if (silMod->getASTContext().hadError() &&
|
||||
silMod->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
|
||||
if (ctx.hadError() &&
|
||||
ctx.LangOpts.AllowModuleWithCompilerErrors)
|
||||
return silMod;
|
||||
|
||||
SILGenModuleRAII scope(*silMod);
|
||||
SILGenModule SGM(*silMod, silMod->getSwiftModule());
|
||||
|
||||
// Emit a specific set of SILDeclRefs if needed.
|
||||
if (auto Sources = desc.SourcesToEmit) {
|
||||
for (auto Source : *Sources)
|
||||
scope.emitSymbolSource(std::move(Source));
|
||||
SGM.emitSymbolSource(std::move(Source));
|
||||
}
|
||||
|
||||
// Emit any whole-files needed.
|
||||
for (auto file : desc.getFilesToEmit()) {
|
||||
if (auto *nextSF = dyn_cast<SourceFile>(file))
|
||||
scope.emitSourceFile(nextSF);
|
||||
SGM.emitSourceFile(nextSF);
|
||||
}
|
||||
|
||||
// Also make sure to process any intermediate files that may contain SIL.
|
||||
@@ -2191,6 +2153,23 @@ ASTLoweringRequest::evaluate(Evaluator &evaluator,
|
||||
primary);
|
||||
}
|
||||
|
||||
// Emit any delayed definitions that were forced.
|
||||
// Emitting these may in turn force more definitions, so we have to take
|
||||
// care to keep pumping the queues.
|
||||
while (!SGM.pendingForcedFunctions.empty()
|
||||
|| !SGM.pendingConformances.empty()) {
|
||||
while (!SGM.pendingForcedFunctions.empty()) {
|
||||
auto &front = SGM.pendingForcedFunctions.front();
|
||||
SGM.emitFunctionDefinition(
|
||||
front, SGM.getEmittedFunction(front, ForDefinition));
|
||||
SGM.pendingForcedFunctions.pop_front();
|
||||
}
|
||||
while (!SGM.pendingConformances.empty()) {
|
||||
(void)SGM.getWitnessTable(SGM.pendingConformances.front());
|
||||
SGM.pendingConformances.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
return silMod;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
namespace swift {
|
||||
class SILBasicBlock;
|
||||
class ForeignAsyncConvention;
|
||||
class SymbolSource;
|
||||
|
||||
namespace Lowering {
|
||||
class TypeConverter;
|
||||
@@ -124,6 +125,12 @@ public:
|
||||
|
||||
ASTContext &getASTContext() { return M.getASTContext(); }
|
||||
|
||||
/// Main entry point.
|
||||
void emitSourceFile(SourceFile *sf);
|
||||
|
||||
/// Lazy entry point for Feature::LazyImmediate.
|
||||
void emitSymbolSource(SymbolSource Source);
|
||||
|
||||
llvm::StringMap<std::pair<std::string, /*isWinner=*/bool>> FileIDsByFilePath;
|
||||
|
||||
static DeclName getMagicFunctionName(SILDeclRef ref);
|
||||
|
||||
@@ -1693,11 +1693,6 @@ SynthesizeDefaultInitRequest::evaluate(Evaluator &evaluator,
|
||||
NominalTypeDecl *decl) const {
|
||||
auto &ctx = decl->getASTContext();
|
||||
|
||||
FrontendStatsTracer StatsTracer(ctx.Stats,
|
||||
"define-default-ctor", decl);
|
||||
PrettyStackTraceDecl stackTrace("defining default constructor for",
|
||||
decl);
|
||||
|
||||
// Create the default constructor.
|
||||
auto ctorKind = decl->isDistributedActor() ?
|
||||
ImplicitConstructorKind::DefaultDistributedActor :
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -parse-as-library -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
|
||||
|
||||
// RUN: %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -stats-output-dir %t/stats-no-lookup -primary-file %t/b.swift %t/a.swift
|
||||
// RUN: %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -stats-output-dir %t/stats-lookup -primary-file %t/c.swift %t/a.swift
|
||||
// RUN: %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -stats-output-dir %t/stats-no-lookup -fine-grained-timers -primary-file %t/b.swift %t/a.swift
|
||||
// RUN: %target-swift-frontend -typecheck -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -stats-output-dir %t/stats-lookup -fine-grained-timers -primary-file %t/c.swift %t/a.swift
|
||||
|
||||
// We use '<=' here instead of '==' to take account of the fact that in debug
|
||||
// builds we'll be doing round-trip checking, which will parse the syntax tree
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %empty-directory(%t/stats-events)
|
||||
// RUN: %empty-directory(%t/stats-entities)
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-events %s -profile-stats-events
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-entities %s -profile-stats-entities
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-events %s -profile-stats-events -Xfrontend -fine-grained-timers
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-entities %s -profile-stats-entities -Xfrontend -fine-grained-timers
|
||||
|
||||
// Need to use %long-tmp because in Windows the * may expand to a path longer
|
||||
// than 260 characters.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events -Xfrontend -fine-grained-timers
|
||||
// RUN: %FileCheck -input-file %t/*.csv %s
|
||||
|
||||
// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","SelfBoundsFromWhereClauseRequest","Sema.SelfBoundsFromWhereClauseRequest",[0-9]+,[0-9]+,"Proto",".*stats_dir_tracer.swift.*"}}
|
||||
|
||||
@@ -149,6 +149,8 @@ def run_once_with_primary(args, ast, rng, primary_idx):
|
||||
[line.split() for line in open(os.path.join(d, trace))]
|
||||
if len(fields) == 2}
|
||||
else:
|
||||
command += ["-fine-grained-timers"]
|
||||
|
||||
if args.debug:
|
||||
command = ["lldb", "--"] + command
|
||||
stats = "stats.json"
|
||||
@@ -633,6 +635,9 @@ def report(args, rng, runs):
|
||||
rows = []
|
||||
for k in keys:
|
||||
vals = [r[k] for r in runs]
|
||||
if all(v == 0 for v in vals):
|
||||
print("Missing data")
|
||||
return True
|
||||
bounded = [max(v, 1) for v in vals]
|
||||
one_fit = False
|
||||
perfect_fit = False
|
||||
|
||||
Reference in New Issue
Block a user