Skip to content

Commit 399a600

Browse files
committed
RequirementMachine: Add -debug-requirement-machine= flag to control debug output
1 parent fe2f42b commit 399a600

File tree

11 files changed

+119
-38
lines changed

11 files changed

+119
-38
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,9 @@ namespace swift {
465465
/// Enables statistics output from the requirement machine.
466466
bool AnalyzeRequirementMachine = false;
467467

468+
/// Enables fine-grained debug output from the requirement machine.
469+
std::string DebugRequirementMachine;
470+
468471
/// Maximum iteration count for requirement machine confluent completion
469472
/// algorithm.
470473
unsigned RequirementMachineStepLimit = 2000;

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-l
276276
def dump_requirement_machine : Flag<["-"], "dump-requirement-machine">,
277277
HelpText<"Enables dumping rewrite systems from the generics implementation">;
278278

279+
def debug_requirement_machine : Joined<["-"], "debug-requirement-machine=">,
280+
HelpText<"Fine-grained debug output from the generics implementation">;
281+
279282
def analyze_requirement_machine : Flag<["-"], "analyze-requirement-machine">,
280283
Flags<[FrontendOption, HelpHidden, DoesNotAffectIncrementalBuild]>,
281284
HelpText<"Print out requirement machine statistics at the end of the compilation job">;

lib/AST/RequirementMachine/Debug.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--- Debug.h - Requirement machine debugging flags ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_RQM_DEBUG_H
14+
#define SWIFT_RQM_DEBUG_H
15+
16+
namespace swift {
17+
18+
namespace rewriting {
19+
20+
enum class DebugFlags : unsigned {
21+
/// Print debug output when simplifying terms.
22+
Simplify = (1<<0),
23+
24+
/// Print debug output when adding rules.
25+
Add = (1<<1),
26+
27+
/// Print debug output when merging associated types.
28+
Merge = (1<<2),
29+
30+
/// Print debug output from the Knuth-Bendix algorithm.
31+
Completion = (1<<3),
32+
33+
/// Print debug output when unifying concrete types in the property map.
34+
ConcreteUnification = (1<<4),
35+
36+
/// Print debug output when concretizing nested types in the property map.
37+
ConcretizeNestedTypes = (1<<5)
38+
};
39+
40+
using DebugOptions = OptionSet<DebugFlags>;
41+
42+
}
43+
44+
}
45+
46+
#endif

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ void PropertyMap::addProperty(
736736
assert(property.isProperty());
737737
auto *props = getOrCreateProperties(key);
738738
props->addProperty(property, Context,
739-
inducedRules, DebugConcreteUnification);
739+
inducedRules, Debug.contains(DebugFlags::ConcreteUnification));
740740
}
741741

742742
/// For each fully-concrete type, find the shortest term having that concrete type.
@@ -772,7 +772,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
772772
if (props->getConformsTo().empty())
773773
continue;
774774

775-
if (DebugConcretizeNestedTypes) {
775+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
776776
if (props->isConcreteType() ||
777777
props->hasSuperclassBound()) {
778778
llvm::dbgs() << "^ Concretizing nested types of ";
@@ -782,7 +782,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
782782
}
783783

784784
if (props->isConcreteType()) {
785-
if (DebugConcretizeNestedTypes) {
785+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
786786
llvm::dbgs() << "- via concrete type requirement\n";
787787
}
788788

@@ -797,7 +797,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
797797
}
798798

799799
if (props->hasSuperclassBound()) {
800-
if (DebugConcretizeNestedTypes) {
800+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
801801
llvm::dbgs() << "- via superclass requirement\n";
802802
}
803803

@@ -863,7 +863,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
863863
const_cast<ProtocolDecl *>(proto));
864864
if (conformance.isInvalid()) {
865865
// FIXME: Diagnose conflict
866-
if (DebugConcretizeNestedTypes) {
866+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
867867
llvm::dbgs() << "^^ " << concreteType << " does not conform to "
868868
<< proto->getName() << "\n";
869869
}
@@ -886,15 +886,15 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
886886
continue;
887887

888888
for (auto *assocType : assocTypes) {
889-
if (DebugConcretizeNestedTypes) {
889+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
890890
llvm::dbgs() << "^^ " << "Looking up type witness for "
891891
<< proto->getName() << ":" << assocType->getName()
892892
<< " on " << concreteType << "\n";
893893
}
894894

895895
auto t = concrete->getTypeWitness(assocType);
896896
if (!t) {
897-
if (DebugConcretizeNestedTypes) {
897+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
898898
llvm::dbgs() << "^^ " << "Type witness for " << assocType->getName()
899899
<< " of " << concreteType << " could not be inferred\n";
900900
}
@@ -904,7 +904,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
904904

905905
auto typeWitness = t->getCanonicalType();
906906

907-
if (DebugConcretizeNestedTypes) {
907+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
908908
llvm::dbgs() << "^^ " << "Type witness for " << assocType->getName()
909909
<< " of " << concreteType << " is " << typeWitness << "\n";
910910
}
@@ -920,7 +920,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
920920
// FIXME: ConcreteTypeInDomainMap should support substitutions so
921921
// that we can remove this.
922922

923-
if (DebugConcretizeNestedTypes) {
923+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
924924
llvm::dbgs() << "^^ Type witness is the same as the concrete type\n";
925925
}
926926

@@ -933,7 +933,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
933933
}
934934

935935
inducedRules.emplace_back(subjectType, constraintType);
936-
if (DebugConcretizeNestedTypes) {
936+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
937937
llvm::dbgs() << "^^ Induced rule " << constraintType
938938
<< " => " << subjectType << "\n";
939939
}
@@ -977,7 +977,7 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
977977
if (found != ConcreteTypeInDomainMap.end()) {
978978
MutableTerm result(found->second);
979979
if (result != subjectType) {
980-
if (DebugConcretizeNestedTypes) {
980+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
981981
llvm::dbgs() << "^^ Type witness can re-use property bag of "
982982
<< found->second << "\n";
983983
}

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <algorithm>
2626
#include <vector>
2727

28+
#include "Debug.h"
2829
#include "ProtocolGraph.h"
2930
#include "RewriteContext.h"
3031
#include "RewriteSystem.h"
@@ -145,8 +146,7 @@ class PropertyMap {
145146
llvm::DenseMap<ConcreteTypeInDomain, Term> ConcreteTypeInDomainMap;
146147

147148
const ProtocolGraph &Protos;
148-
unsigned DebugConcreteUnification : 1;
149-
unsigned DebugConcretizeNestedTypes : 1;
149+
DebugOptions Debug;
150150

151151
PropertyBag *getOrCreateProperties(Term key);
152152

@@ -159,8 +159,7 @@ class PropertyMap {
159159
explicit PropertyMap(RewriteContext &ctx,
160160
const ProtocolGraph &protos)
161161
: Context(ctx), Protos(protos) {
162-
DebugConcreteUnification = false;
163-
DebugConcretizeNestedTypes = false;
162+
Debug = ctx.getDebugOptions();
164163
}
165164

166165
~PropertyMap();

lib/AST/RequirementMachine/RewriteContext.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,33 @@
1919
using namespace swift;
2020
using namespace rewriting;
2121

22+
/// Build a DebugOptions by parsing a comma-separated list of debug flags.
23+
static DebugOptions parseDebugFlags(StringRef debugFlags) {
24+
DebugOptions result;
25+
26+
SmallVector<StringRef, 2> debug;
27+
debugFlags.split(debug, ',');
28+
for (auto flagStr : debug) {
29+
auto flag = llvm::StringSwitch<Optional<DebugFlags>>(flagStr)
30+
.Case("simplify", DebugFlags::Simplify)
31+
.Case("add", DebugFlags::Add)
32+
.Case("merge", DebugFlags::Merge)
33+
.Case("completion", DebugFlags::Completion)
34+
.Case("concrete-unification", DebugFlags::ConcreteUnification)
35+
.Case("concretize-nested-types", DebugFlags::ConcretizeNestedTypes)
36+
.Default(None);
37+
if (!flag) {
38+
llvm::errs() << "Unknown debug flag in -debug-requirement-machine "
39+
<< flagStr << "\n";
40+
abort();
41+
}
42+
43+
result |= *flag;
44+
}
45+
46+
return result;
47+
}
48+
2249
RewriteContext::RewriteContext(ASTContext &ctx)
2350
: Context(ctx),
2451
Stats(ctx.Stats),
@@ -28,6 +55,9 @@ RewriteContext::RewriteContext(ASTContext &ctx)
2855
RuleTrieRootHistogram(16),
2956
PropertyTrieHistogram(16, /*Start=*/1),
3057
PropertyTrieRootHistogram(16) {
58+
auto debugFlags = StringRef(ctx.LangOpts.DebugRequirementMachine);
59+
if (!debugFlags.empty())
60+
Debug = parseDebugFlags(debugFlags);
3161
}
3262

3363
Term RewriteContext::getTermForType(CanType paramType,

lib/AST/RequirementMachine/RewriteContext.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/DenseMap.h"
2020
#include "llvm/ADT/FoldingSet.h"
2121
#include "llvm/Support/Allocator.h"
22+
#include "Debug.h"
2223
#include "Histogram.h"
2324
#include "Symbol.h"
2425
#include "Term.h"
@@ -51,13 +52,15 @@ class RewriteContext final {
5152
/// Cache for merged associated type symbols.
5253
llvm::DenseMap<std::pair<Symbol, Symbol>, Symbol> MergedAssocTypes;
5354

55+
ASTContext &Context;
56+
57+
DebugOptions Debug;
58+
5459
RewriteContext(const RewriteContext &) = delete;
5560
RewriteContext(RewriteContext &&) = delete;
5661
RewriteContext &operator=(const RewriteContext &) = delete;
5762
RewriteContext &operator=(RewriteContext &&) = delete;
5863

59-
ASTContext &Context;
60-
6164
public:
6265
/// Statistics.
6366
UnifiedStatsReporter *Stats;
@@ -72,6 +75,8 @@ class RewriteContext final {
7275

7376
explicit RewriteContext(ASTContext &ctx);
7477

78+
DebugOptions getDebugOptions() const { return Debug; }
79+
7580
Term getTermForType(CanType paramType, const ProtocolDecl *proto);
7681

7782
MutableTerm getMutableTermForType(CanType paramType,

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,7 @@ using namespace swift;
2424
using namespace rewriting;
2525

2626
RewriteSystem::RewriteSystem(RewriteContext &ctx)
27-
: Context(ctx) {
28-
DebugSimplify = false;
29-
DebugAdd = false;
30-
DebugMerge = false;
31-
DebugCompletion = false;
32-
}
27+
: Context(ctx), Debug(ctx.getDebugOptions()) {}
3328

3429
RewriteSystem::~RewriteSystem() {
3530
Trie.updateHistograms(Context.RuleTrieHistogram,
@@ -93,7 +88,7 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
9388

9489
assert(lhs.compare(rhs, Protos) > 0);
9590

96-
if (DebugAdd) {
91+
if (Debug.contains(DebugFlags::Add)) {
9792
llvm::dbgs() << "# Adding rule " << lhs << " => " << rhs << "\n";
9893
}
9994

@@ -106,7 +101,7 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
106101
llvm::errs() << "Old rule #" << *oldRuleID << ": ";
107102
oldRule.dump(llvm::errs());
108103
llvm::errs() << "\nTrying to replay what happened when I simplified this term:\n";
109-
DebugSimplify = true;
104+
Debug |= DebugFlags::Simplify;
110105
MutableTerm term = lhs;
111106
simplify(lhs);
112107

@@ -135,7 +130,7 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
135130
bool RewriteSystem::simplify(MutableTerm &term) const {
136131
bool changed = false;
137132

138-
if (DebugSimplify) {
133+
if (Debug.contains(DebugFlags::Simplify)) {
139134
llvm::dbgs() << "= Term " << term << "\n";
140135
}
141136

@@ -149,7 +144,7 @@ bool RewriteSystem::simplify(MutableTerm &term) const {
149144
if (ruleID) {
150145
const auto &rule = Rules[*ruleID];
151146
if (!rule.isDeleted()) {
152-
if (DebugSimplify) {
147+
if (Debug.contains(DebugFlags::Simplify)) {
153148
llvm::dbgs() << "== Rule #" << *ruleID << ": " << rule << "\n";
154149
}
155150

@@ -158,7 +153,7 @@ bool RewriteSystem::simplify(MutableTerm &term) const {
158153

159154
term.rewriteSubTerm(from, to, rule.getRHS());
160155

161-
if (DebugSimplify) {
156+
if (Debug.contains(DebugFlags::Simplify)) {
162157
llvm::dbgs() << "=== Result " << term << "\n";
163158
}
164159

@@ -205,7 +200,7 @@ void RewriteSystem::simplifyRewriteSystem() {
205200
if (Rules[*otherRuleID].isDeleted())
206201
continue;
207202

208-
if (DebugCompletion) {
203+
if (Debug.contains(DebugFlags::Completion)) {
209204
const auto &otherRule = Rules[ruleID];
210205
llvm::dbgs() << "$ Deleting rule " << rule << " because "
211206
<< "its left hand side contains " << otherRule

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/ADT/DenseSet.h"
1717

18+
#include "Debug.h"
1819
#include "ProtocolGraph.h"
1920
#include "Symbol.h"
2021
#include "Term.h"
@@ -111,11 +112,7 @@ class RewriteSystem final {
111112
/// Pairs of rules which have already been checked for overlap.
112113
llvm::DenseSet<std::pair<unsigned, unsigned>> CheckedOverlaps;
113114

114-
/// Set these to true to enable debugging output.
115-
unsigned DebugSimplify : 1;
116-
unsigned DebugAdd : 1;
117-
unsigned DebugMerge : 1;
118-
unsigned DebugCompletion : 1;
115+
DebugOptions Debug;
119116

120117
public:
121118
explicit RewriteSystem(RewriteContext &ctx);

lib/AST/RequirementMachine/RewriteSystemCompletion.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,14 @@ void RewriteSystem::processMergedAssociatedTypes() {
219219
// If we have X.[P2:T] => Y.[P1:T], add a new pair of rules:
220220
// X.[P1:T] => X.[P1&P2:T]
221221
// X.[P2:T] => X.[P1&P2:T]
222-
if (DebugMerge) {
222+
if (Debug.contains(DebugFlags::Merge)) {
223223
llvm::dbgs() << "## Associated type merge candidate ";
224224
llvm::dbgs() << lhs << " => " << rhs << "\n";
225225
}
226226

227227
auto mergedSymbol = Context.mergeAssociatedTypes(lhs.back(), rhs.back(),
228228
Protos);
229-
if (DebugMerge) {
229+
if (Debug.contains(DebugFlags::Merge)) {
230230
llvm::dbgs() << "### Merged symbol " << mergedSymbol << "\n";
231231
}
232232

@@ -259,7 +259,7 @@ void RewriteSystem::processMergedAssociatedTypes() {
259259
// or
260260
//
261261
// [P2:T].[Q] => [P2:T]
262-
if (DebugMerge) {
262+
if (Debug.contains(DebugFlags::Merge)) {
263263
llvm::dbgs() << "### Lifting conformance rule " << otherRule << "\n";
264264
}
265265

@@ -431,7 +431,7 @@ RewriteSystem::computeConfluentCompletion(unsigned maxIterations,
431431
// Try to repair the confluence violation by adding a new rule.
432432
resolvedCriticalPairs.push_back(computeCriticalPair(from, lhs, rhs));
433433

434-
if (DebugCompletion) {
434+
if (Debug.contains(DebugFlags::Completion)) {
435435
const auto &pair = resolvedCriticalPairs.back();
436436

437437
llvm::dbgs() << "$ Overlapping rules: (#" << i << ") ";

0 commit comments

Comments
 (0)