@@ -44,79 +44,82 @@ class MainVisitor:
4444 {
4545 std::string typeName = recordDecl->getQualifiedNameAsString ();
4646
47+ // Ignore (system/non-GC types) before seeing "Memory::NoWriteBarrierField"
4748 if (!_barrierTypeDefined)
4849 {
49- if (typeName == " Memory::NoWriteBarrierField" )
50- {
51- _barrierTypeDefined = true ;
52- }
53- else
50+ if (typeName != " Memory::NoWriteBarrierField" )
5451 {
5552 return true ;
5653 }
54+
55+ _barrierTypeDefined = true ;
5756 }
5857
59- if (recordDecl->hasDefinition ())
58+ if (! recordDecl->hasDefinition ())
6059 {
61- bool hasUnbarrieredPointer = false ;
62- const FieldDecl* unbarrieredPointerField = nullptr ;
63- bool hasBarrieredField = false ;
60+ return true ;
61+ }
6462
65- for (auto field : recordDecl->fields ())
66- {
67- const QualType qualType = field->getType ();
68- const Type* type = qualType.getTypePtr ();
63+ bool hasUnbarrieredPointer = false ;
64+ const FieldDecl* unbarrieredPointerField = nullptr ;
65+ bool hasBarrieredField = false ;
6966
70- if (type->isPointerType ())
67+ for (auto field : recordDecl->fields ())
68+ {
69+ const QualType qualType = field->getType ();
70+ const Type* type = qualType.getTypePtr ();
71+
72+ if (type->isPointerType ())
73+ {
74+ hasUnbarrieredPointer = true ;
75+ if (!unbarrieredPointerField)
7176 {
72- hasUnbarrieredPointer = true ;
73- if (!unbarrieredPointerField)
74- {
75- unbarrieredPointerField = field;
76- }
77+ unbarrieredPointerField = field;
7778 }
78- else
79+ }
80+ else
81+ {
82+ auto fieldTypeName = qualType.getAsString ();
83+ if (fieldTypeName.find (" WriteBarrierPtr" ) == 0 ) // starts with
7984 {
80- auto fieldTypeName = qualType.getAsString ();
81- if (fieldTypeName.find (" WriteBarrierPtr" ) == 0 )
85+ hasBarrieredField = true ;
86+ }
87+ else if (type->isCompoundType ())
88+ {
89+ // If the field is a compound type,
90+ // check if it is a fully barriered type or
91+ // has unprotected pointer fields
92+ if (_pointerClasses.find (fieldTypeName) != _pointerClasses.end ())
8293 {
83- hasBarrieredField = true ;
94+ hasUnbarrieredPointer = true ;
95+ if (!unbarrieredPointerField)
96+ unbarrieredPointerField = field;
8497 }
85- else if (type-> isCompoundType ())
98+ else if (_barrieredClasses. find (fieldTypeName) != _barrieredClasses. end ())
8699 {
87- // If the field is a compound type,
88- // check if it is a fully barriered type or
89- // has unprotected pointer fields
90- if (_pointerClasses.find (fieldTypeName) != _pointerClasses.end ())
91- {
92- hasUnbarrieredPointer = true ;
93- if (!unbarrieredPointerField)
94- unbarrieredPointerField = field;
95- }
96- else if (_barrieredClasses.find (fieldTypeName) != _barrieredClasses.end ())
97- {
98- hasBarrieredField = true ;
99- }
100+ hasBarrieredField = true ;
100101 }
101102 }
102103 }
104+ }
103105
104- if (hasUnbarrieredPointer)
106+ if (hasUnbarrieredPointer)
107+ {
108+ _pointerClasses.insert (typeName);
109+ }
110+
111+ if (hasBarrieredField)
112+ {
113+ llvm::outs () << " Type with barrier found: \" " << typeName << " \"\n " ;
114+ if (!hasUnbarrieredPointer)
105115 {
106- _pointerClasses .insert (typeName);
116+ _barrieredClasses .insert (typeName);
107117 }
108-
109- if (hasBarrieredField)
118+ else
110119 {
111- llvm::outs ()<<" Type with barrier found: \" " <<typeName<<" \"\n " ;
112- if (!hasUnbarrieredPointer)
113- {
114- _barrieredClasses.insert (typeName);
115- }
116- else
117- {
118- llvm::outs ()<<" Unbarriered field: \" " <<unbarrieredPointerField->getQualifiedNameAsString ()<<" \"\n " ;
119- }
120+ llvm::outs () << " ERROR: Unbarriered field: \" "
121+ << unbarrieredPointerField->getQualifiedNameAsString ()
122+ << " \"\n " ;
120123 }
121124 }
122125
@@ -135,9 +138,9 @@ class MainVisitor:
135138 return true ;
136139 }
137140
138- void RecordWriteBarrierAllocation (const string & allocationType)
141+ void RecordWriteBarrierAllocation (const QualType & allocationType)
139142 {
140- _barrierAllocations.insert (allocationType);
143+ _barrierAllocations.insert (allocationType. getTypePtr () );
141144 }
142145
143146 void RecordRecyclerAllocation (const string& allocationFunction, const string& type)
@@ -151,40 +154,71 @@ class MainVisitor:
151154 }
152155
153156#define Dump (coll ) \
154- dump (_## coll, #coll)
157+ dump (# coll, _# #coll)
155158
156159 void Inspect ()
157160 {
158161 Dump (pointerClasses);
159162 Dump (barrieredClasses);
160163
161- llvm::outs ()<< " Recycler allocations\n " ;
164+ llvm::outs () << " Recycler allocations\n " ;
162165 for (auto item : _allocatorTypeMap)
163166 {
164- dump (item.second , item. first .c_str ());
167+ dump (item.first .c_str (), item. second );
165168 }
166169
167170 Dump (barrierAllocations);
168171 }
169172
170173private:
171- void dump (const set<string>& set, const char * name)
174+ template <class Set , class DumpItemFunc >
175+ void dump (const char * name, const Set& set, const DumpItemFunc& func)
172176 {
173- llvm::outs ()<< " -------------------------\n\n " ;
174- llvm::outs ()<< name<< " \n " ;
175- llvm::outs ()<< " -------------------------\n\n " ;
177+ llvm::outs () << " -------------------------\n\n " ;
178+ llvm::outs () << name << " \n " ;
179+ llvm::outs () << " -------------------------\n\n " ;
176180 for (auto item : set)
177181 {
178- llvm::outs ()<< " " << item<< " \n " ;
182+ func ( llvm::outs (), item) ;
179183 }
180- llvm::outs ()<<" -------------------------\n\n " ;
184+ llvm::outs () << " -------------------------\n\n " ;
185+ }
186+
187+ template <class Item >
188+ void dump (const char * name, const set<Item>& set)
189+ {
190+ dump (name, set, [](raw_ostream& out, const Item& item)
191+ {
192+ out << " " << item << " \n " ;
193+ });
194+ }
195+
196+ void dump (const char * name, const set<const Type*> set)
197+ {
198+ dump (name, set, [this ](raw_ostream& out, const Type* type)
199+ {
200+ out << " " << QualType (type, 0 ).getAsString () << " \n " ;
201+
202+ // Examine underlying "canonical" type (strip typedef) and try to
203+ // match declaration. If we find it in _pointerClasses, the type
204+ // is missing write-barrier decorations.
205+ auto r = type->getCanonicalTypeInternal ()->getAsCXXRecordDecl ();
206+ if (r)
207+ {
208+ auto typeName = r->getQualifiedNameAsString ();
209+ if (_pointerClasses.find (typeName) != _pointerClasses.end ())
210+ {
211+ out << " ERROR: Unbarried type " << typeName << " \n " ;
212+ }
213+ }
214+ });
181215 }
182216
183217 bool _barrierTypeDefined;
184218 map<string, set<string> > _allocatorTypeMap;
185219 set<string> _pointerClasses;
186220 set<string> _barrieredClasses;
187- set<string > _barrierAllocations;
221+ set<const Type* > _barrierAllocations;
188222};
189223
190224static bool isCastToRecycler (const CXXStaticCastExpr* castNode)
@@ -240,9 +274,9 @@ bool CheckAllocationsInFunctionVisitor::VisitCXXNewExpr(CXXNewExpr* newExpr)
240274
241275 if (allocationFunctionStr.find (" WithBarrier" ) != string::npos)
242276 {
243- llvm::outs ()<< " In \" " << _functionDecl->getQualifiedNameAsString ()<< " \"\n " ;
244- llvm::outs ()<< " Allocating \" " << allocatedTypeStr<< " \" in write barriered memory\n " ;
245- _mainVisitor->RecordWriteBarrierAllocation (allocatedTypeStr );
277+ llvm::outs () << " In \" " << _functionDecl->getQualifiedNameAsString () << " \"\n " ;
278+ llvm::outs () << " Allocating \" " << allocatedTypeStr << " \" in write barriered memory\n " ;
279+ _mainVisitor->RecordWriteBarrierAllocation (allocatedType );
246280 }
247281 }
248282 else
0 commit comments