@@ -38,15 +38,6 @@ class SwiftDispatcher {
38
38
emit (ElementIsUnknownTrap{label});
39
39
}
40
40
41
- private:
42
- // types to be supported by assignNewLabel/fetchLabel need to be listed here
43
- using Store = TrapLabelStore<swift::Decl,
44
- swift::Stmt,
45
- swift::Expr,
46
- swift::Pattern,
47
- swift::TypeRepr,
48
- swift::TypeBase>;
49
-
50
41
// This method gives a TRAP label for already emitted AST node.
51
42
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
52
43
// visitor (see `visit(T *)` methods below).
@@ -72,52 +63,109 @@ class SwiftDispatcher {
72
63
return {};
73
64
}
74
65
66
+ // convenience `fetchLabel` overload for `swift::Type` (which is just a wrapper for
67
+ // `swift::TypeBase*`)
68
+ TrapLabel<TypeTag> fetchLabel (swift::Type t) { return fetchLabel (t.getPointer ()); }
69
+
70
+ TrapLabel<AstNodeTag> fetchLabel (swift::ASTNode node) {
71
+ return fetchLabelFromUnion<AstNodeTag>(node);
72
+ }
73
+
75
74
// Due to the lazy emission approach, we must assign a label to a corresponding AST node before
76
75
// it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
77
76
// declarations
78
77
template <typename E>
79
78
TrapLabelOf<E> assignNewLabel (E* e) {
80
79
assert (waitingForNewLabel == Store::Handle{e} && " assignNewLabel called on wrong entity" );
81
- auto label = getLabel<TrapTagOf<E>>();
82
- trap.assignStar (label);
80
+ auto label = createLabel<TrapTagOf<E>>();
83
81
store.insert (e, label);
84
82
waitingForNewLabel = std::monostate{};
85
83
return label;
86
84
}
87
85
88
86
template <typename Tag>
89
- TrapLabel<Tag> getLabel () {
90
- return arena.allocateLabel <Tag>();
87
+ TrapLabel<Tag> createLabel () {
88
+ auto ret = arena.allocateLabel <Tag>();
89
+ trap.assignStar (ret);
90
+ return ret;
91
+ }
92
+
93
+ template <typename Tag, typename ... Args>
94
+ TrapLabel<Tag> createLabel (Args&&... args) {
95
+ auto ret = arena.allocateLabel <Tag>();
96
+ trap.assignKey (ret, std::forward<Args>(args)...);
97
+ return ret;
91
98
}
92
99
93
100
template <typename Locatable>
94
101
void attachLocation (Locatable locatable, TrapLabel<LocatableTag> locatableLabel) {
95
102
attachLocation (&locatable, locatableLabel);
96
103
}
97
104
98
- // Emits a Location TRAP entry and attaches it to an AST node
105
+ // Emits a Location TRAP entry and attaches it to a `Locatable` trap label
99
106
template <typename Locatable>
100
107
void attachLocation (Locatable* locatable, TrapLabel<LocatableTag> locatableLabel) {
101
- auto start = locatable->getStartLoc ();
102
- auto end = locatable->getEndLoc ();
108
+ attachLocation (locatable->getStartLoc (), locatable->getEndLoc (), locatableLabel);
109
+ }
110
+
111
+ // Emits a Location TRAP entry for a list of swift entities and attaches it to a `Locatable` trap
112
+ // label
113
+ template <typename Locatable>
114
+ void attachLocation (llvm::MutableArrayRef<Locatable>* locatables,
115
+ TrapLabel<LocatableTag> locatableLabel) {
116
+ if (locatables->empty ()) {
117
+ return ;
118
+ }
119
+ attachLocation (locatables->front ().getStartLoc (), locatables->back ().getEndLoc (),
120
+ locatableLabel);
121
+ }
122
+
123
+ private:
124
+ // types to be supported by assignNewLabel/fetchLabel need to be listed here
125
+ using Store = TrapLabelStore<swift::Decl,
126
+ swift::Stmt,
127
+ swift::StmtCondition,
128
+ swift::CaseLabelItem,
129
+ swift::Expr,
130
+ swift::Pattern,
131
+ swift::TypeRepr,
132
+ swift::TypeBase>;
133
+
134
+ void attachLocation (swift::SourceLoc start,
135
+ swift::SourceLoc end,
136
+ TrapLabel<LocatableTag> locatableLabel) {
103
137
if (!start.isValid () || !end.isValid ()) {
104
138
// invalid locations seem to come from entities synthesized by the compiler
105
139
return ;
106
140
}
107
141
std::string filepath = getFilepath (start);
108
- auto fileLabel = arena.allocateLabel <FileTag>();
109
- trap.assignKey (fileLabel, filepath);
142
+ auto fileLabel = createLabel<FileTag>(filepath);
110
143
// TODO: do not emit duplicate trap entries for Files
111
144
trap.emit (FilesTrap{fileLabel, filepath});
112
145
auto [startLine, startColumn] = sourceManager.getLineAndColumnInBuffer (start);
113
146
auto [endLine, endColumn] = sourceManager.getLineAndColumnInBuffer (end);
114
- auto locLabel = arena.allocateLabel <LocationTag>();
115
- trap.assignKey (locLabel, ' {' , fileLabel, " }:" , startLine, ' :' , startColumn, ' :' , endLine, ' :' ,
116
- endColumn);
147
+ auto locLabel = createLabel<LocationTag>(' {' , fileLabel, " }:" , startLine, ' :' , startColumn, ' :' ,
148
+ endLine, ' :' , endColumn);
117
149
trap.emit (LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
118
150
trap.emit (LocatablesTrap{locatableLabel, locLabel});
119
151
}
120
152
153
+ template <typename Tag, typename ... Ts>
154
+ TrapLabel<Tag> fetchLabelFromUnion (const llvm::PointerUnion<Ts...> u) {
155
+ TrapLabel<Tag> ret{};
156
+ assert ((... || fetchLabelFromUnionCase<Tag, Ts>(u, ret)) && " llvm::PointerUnion not set" );
157
+ return ret;
158
+ }
159
+
160
+ template <typename Tag, typename T, typename ... Ts>
161
+ bool fetchLabelFromUnionCase (const llvm::PointerUnion<Ts...> u, TrapLabel<Tag>& output) {
162
+ if (auto e = u.template dyn_cast <T>()) {
163
+ output = fetchLabel (e);
164
+ return true ;
165
+ }
166
+ return false ;
167
+ }
168
+
121
169
std::string getFilepath (swift::SourceLoc loc) {
122
170
// TODO: this needs more testing
123
171
// TODO: check canonicaliztion of names on a case insensitive filesystems
@@ -135,6 +183,8 @@ class SwiftDispatcher {
135
183
// which are to be introduced in follow-up PRs
136
184
virtual void visit (swift::Decl* decl) = 0;
137
185
virtual void visit (swift::Stmt* stmt) = 0;
186
+ virtual void visit (swift::StmtCondition* cond) = 0;
187
+ virtual void visit (swift::CaseLabelItem* item) = 0;
138
188
virtual void visit (swift::Expr* expr) = 0;
139
189
virtual void visit (swift::Pattern* pattern) = 0;
140
190
virtual void visit (swift::TypeRepr* type) = 0;
0 commit comments