@@ -38,15 +38,6 @@ class SwiftDispatcher {
3838 emit (ElementIsUnknownTrap{label});
3939 }
4040
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-
5041 // This method gives a TRAP label for already emitted AST node.
5142 // If the AST node was not emitted yet, then the emission is dispatched to a corresponding
5243 // visitor (see `visit(T *)` methods below).
@@ -72,52 +63,109 @@ class SwiftDispatcher {
7263 return {};
7364 }
7465
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+
7574 // Due to the lazy emission approach, we must assign a label to a corresponding AST node before
7675 // it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
7776 // declarations
7877 template <typename E>
7978 TrapLabelOf<E> assignNewLabel (E* e) {
8079 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>>();
8381 store.insert (e, label);
8482 waitingForNewLabel = std::monostate{};
8583 return label;
8684 }
8785
8886 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;
9198 }
9299
93100 template <typename Locatable>
94101 void attachLocation (Locatable locatable, TrapLabel<LocatableTag> locatableLabel) {
95102 attachLocation (&locatable, locatableLabel);
96103 }
97104
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
99106 template <typename Locatable>
100107 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) {
103137 if (!start.isValid () || !end.isValid ()) {
104138 // invalid locations seem to come from entities synthesized by the compiler
105139 return ;
106140 }
107141 std::string filepath = getFilepath (start);
108- auto fileLabel = arena.allocateLabel <FileTag>();
109- trap.assignKey (fileLabel, filepath);
142+ auto fileLabel = createLabel<FileTag>(filepath);
110143 // TODO: do not emit duplicate trap entries for Files
111144 trap.emit (FilesTrap{fileLabel, filepath});
112145 auto [startLine, startColumn] = sourceManager.getLineAndColumnInBuffer (start);
113146 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);
117149 trap.emit (LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
118150 trap.emit (LocatablesTrap{locatableLabel, locLabel});
119151 }
120152
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+
121169 std::string getFilepath (swift::SourceLoc loc) {
122170 // TODO: this needs more testing
123171 // TODO: check canonicaliztion of names on a case insensitive filesystems
@@ -135,6 +183,8 @@ class SwiftDispatcher {
135183 // which are to be introduced in follow-up PRs
136184 virtual void visit (swift::Decl* decl) = 0;
137185 virtual void visit (swift::Stmt* stmt) = 0;
186+ virtual void visit (swift::StmtCondition* cond) = 0;
187+ virtual void visit (swift::CaseLabelItem* item) = 0;
138188 virtual void visit (swift::Expr* expr) = 0;
139189 virtual void visit (swift::Pattern* pattern) = 0;
140190 virtual void visit (swift::TypeRepr* type) = 0;
0 commit comments