1 //===-- MPIFunctionClassifier.cpp - classifies MPI functions ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines functionality to identify and classify MPI functions.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
15 #include "llvm/ADT/STLExtras.h"
16 
17 namespace clang {
18 namespace ento {
19 namespace mpi {
20 
21 void MPIFunctionClassifier::identifierInit(ASTContext &ASTCtx) {
22   // Initialize function identifiers.
23   initPointToPointIdentifiers(ASTCtx);
24   initCollectiveIdentifiers(ASTCtx);
25   initAdditionalIdentifiers(ASTCtx);
26 }
27 
28 void MPIFunctionClassifier::initPointToPointIdentifiers(ASTContext &ASTCtx) {
29   // Copy identifiers into the correct classification containers.
30   IdentInfo_MPI_Send = &ASTCtx.Idents.get("MPI_Send");
31   MPIPointToPointTypes.push_back(IdentInfo_MPI_Send);
32   MPIType.push_back(IdentInfo_MPI_Send);
33   assert(IdentInfo_MPI_Send);
34 
35   IdentInfo_MPI_Isend = &ASTCtx.Idents.get("MPI_Isend");
36   MPIPointToPointTypes.push_back(IdentInfo_MPI_Isend);
37   MPINonBlockingTypes.push_back(IdentInfo_MPI_Isend);
38   MPIType.push_back(IdentInfo_MPI_Isend);
39   assert(IdentInfo_MPI_Isend);
40 
41   IdentInfo_MPI_Ssend = &ASTCtx.Idents.get("MPI_Ssend");
42   MPIPointToPointTypes.push_back(IdentInfo_MPI_Ssend);
43   MPIType.push_back(IdentInfo_MPI_Ssend);
44   assert(IdentInfo_MPI_Ssend);
45 
46   IdentInfo_MPI_Issend = &ASTCtx.Idents.get("MPI_Issend");
47   MPIPointToPointTypes.push_back(IdentInfo_MPI_Issend);
48   MPINonBlockingTypes.push_back(IdentInfo_MPI_Issend);
49   MPIType.push_back(IdentInfo_MPI_Issend);
50   assert(IdentInfo_MPI_Issend);
51 
52   IdentInfo_MPI_Bsend = &ASTCtx.Idents.get("MPI_Bsend");
53   MPIPointToPointTypes.push_back(IdentInfo_MPI_Bsend);
54   MPIType.push_back(IdentInfo_MPI_Bsend);
55   assert(IdentInfo_MPI_Bsend);
56 
57   IdentInfo_MPI_Ibsend = &ASTCtx.Idents.get("MPI_Ibsend");
58   MPIPointToPointTypes.push_back(IdentInfo_MPI_Ibsend);
59   MPINonBlockingTypes.push_back(IdentInfo_MPI_Ibsend);
60   MPIType.push_back(IdentInfo_MPI_Ibsend);
61   assert(IdentInfo_MPI_Ibsend);
62 
63   IdentInfo_MPI_Rsend = &ASTCtx.Idents.get("MPI_Rsend");
64   MPIPointToPointTypes.push_back(IdentInfo_MPI_Rsend);
65   MPIType.push_back(IdentInfo_MPI_Rsend);
66   assert(IdentInfo_MPI_Rsend);
67 
68   IdentInfo_MPI_Irsend = &ASTCtx.Idents.get("MPI_Irsend");
69   MPIPointToPointTypes.push_back(IdentInfo_MPI_Irsend);
70   MPIType.push_back(IdentInfo_MPI_Irsend);
71   assert(IdentInfo_MPI_Irsend);
72 
73   IdentInfo_MPI_Recv = &ASTCtx.Idents.get("MPI_Recv");
74   MPIPointToPointTypes.push_back(IdentInfo_MPI_Recv);
75   MPIType.push_back(IdentInfo_MPI_Recv);
76   assert(IdentInfo_MPI_Recv);
77 
78   IdentInfo_MPI_Irecv = &ASTCtx.Idents.get("MPI_Irecv");
79   MPIPointToPointTypes.push_back(IdentInfo_MPI_Irecv);
80   MPINonBlockingTypes.push_back(IdentInfo_MPI_Irecv);
81   MPIType.push_back(IdentInfo_MPI_Irecv);
82   assert(IdentInfo_MPI_Irecv);
83 }
84 
85 void MPIFunctionClassifier::initCollectiveIdentifiers(ASTContext &ASTCtx) {
86   // Copy identifiers into the correct classification containers.
87   IdentInfo_MPI_Scatter = &ASTCtx.Idents.get("MPI_Scatter");
88   MPICollectiveTypes.push_back(IdentInfo_MPI_Scatter);
89   MPIPointToCollTypes.push_back(IdentInfo_MPI_Scatter);
90   MPIType.push_back(IdentInfo_MPI_Scatter);
91   assert(IdentInfo_MPI_Scatter);
92 
93   IdentInfo_MPI_Iscatter = &ASTCtx.Idents.get("MPI_Iscatter");
94   MPICollectiveTypes.push_back(IdentInfo_MPI_Iscatter);
95   MPIPointToCollTypes.push_back(IdentInfo_MPI_Iscatter);
96   MPINonBlockingTypes.push_back(IdentInfo_MPI_Iscatter);
97   MPIType.push_back(IdentInfo_MPI_Iscatter);
98   assert(IdentInfo_MPI_Iscatter);
99 
100   IdentInfo_MPI_Gather = &ASTCtx.Idents.get("MPI_Gather");
101   MPICollectiveTypes.push_back(IdentInfo_MPI_Gather);
102   MPICollToPointTypes.push_back(IdentInfo_MPI_Gather);
103   MPIType.push_back(IdentInfo_MPI_Gather);
104   assert(IdentInfo_MPI_Gather);
105 
106   IdentInfo_MPI_Igather = &ASTCtx.Idents.get("MPI_Igather");
107   MPICollectiveTypes.push_back(IdentInfo_MPI_Igather);
108   MPICollToPointTypes.push_back(IdentInfo_MPI_Igather);
109   MPINonBlockingTypes.push_back(IdentInfo_MPI_Igather);
110   MPIType.push_back(IdentInfo_MPI_Igather);
111   assert(IdentInfo_MPI_Igather);
112 
113   IdentInfo_MPI_Allgather = &ASTCtx.Idents.get("MPI_Allgather");
114   MPICollectiveTypes.push_back(IdentInfo_MPI_Allgather);
115   MPICollToCollTypes.push_back(IdentInfo_MPI_Allgather);
116   MPIType.push_back(IdentInfo_MPI_Allgather);
117   assert(IdentInfo_MPI_Allgather);
118 
119   IdentInfo_MPI_Iallgather = &ASTCtx.Idents.get("MPI_Iallgather");
120   MPICollectiveTypes.push_back(IdentInfo_MPI_Iallgather);
121   MPICollToCollTypes.push_back(IdentInfo_MPI_Iallgather);
122   MPINonBlockingTypes.push_back(IdentInfo_MPI_Iallgather);
123   MPIType.push_back(IdentInfo_MPI_Iallgather);
124   assert(IdentInfo_MPI_Iallgather);
125 
126   IdentInfo_MPI_Bcast = &ASTCtx.Idents.get("MPI_Bcast");
127   MPICollectiveTypes.push_back(IdentInfo_MPI_Bcast);
128   MPIPointToCollTypes.push_back(IdentInfo_MPI_Bcast);
129   MPIType.push_back(IdentInfo_MPI_Bcast);
130   assert(IdentInfo_MPI_Bcast);
131 
132   IdentInfo_MPI_Ibcast = &ASTCtx.Idents.get("MPI_Ibcast");
133   MPICollectiveTypes.push_back(IdentInfo_MPI_Ibcast);
134   MPIPointToCollTypes.push_back(IdentInfo_MPI_Ibcast);
135   MPINonBlockingTypes.push_back(IdentInfo_MPI_Ibcast);
136   MPIType.push_back(IdentInfo_MPI_Ibcast);
137   assert(IdentInfo_MPI_Ibcast);
138 
139   IdentInfo_MPI_Reduce = &ASTCtx.Idents.get("MPI_Reduce");
140   MPICollectiveTypes.push_back(IdentInfo_MPI_Reduce);
141   MPICollToPointTypes.push_back(IdentInfo_MPI_Reduce);
142   MPIType.push_back(IdentInfo_MPI_Reduce);
143   assert(IdentInfo_MPI_Reduce);
144 
145   IdentInfo_MPI_Ireduce = &ASTCtx.Idents.get("MPI_Ireduce");
146   MPICollectiveTypes.push_back(IdentInfo_MPI_Ireduce);
147   MPICollToPointTypes.push_back(IdentInfo_MPI_Ireduce);
148   MPINonBlockingTypes.push_back(IdentInfo_MPI_Ireduce);
149   MPIType.push_back(IdentInfo_MPI_Ireduce);
150   assert(IdentInfo_MPI_Ireduce);
151 
152   IdentInfo_MPI_Allreduce = &ASTCtx.Idents.get("MPI_Allreduce");
153   MPICollectiveTypes.push_back(IdentInfo_MPI_Allreduce);
154   MPICollToCollTypes.push_back(IdentInfo_MPI_Allreduce);
155   MPIType.push_back(IdentInfo_MPI_Allreduce);
156   assert(IdentInfo_MPI_Allreduce);
157 
158   IdentInfo_MPI_Iallreduce = &ASTCtx.Idents.get("MPI_Iallreduce");
159   MPICollectiveTypes.push_back(IdentInfo_MPI_Iallreduce);
160   MPICollToCollTypes.push_back(IdentInfo_MPI_Iallreduce);
161   MPINonBlockingTypes.push_back(IdentInfo_MPI_Iallreduce);
162   MPIType.push_back(IdentInfo_MPI_Iallreduce);
163   assert(IdentInfo_MPI_Iallreduce);
164 
165   IdentInfo_MPI_Alltoall = &ASTCtx.Idents.get("MPI_Alltoall");
166   MPICollectiveTypes.push_back(IdentInfo_MPI_Alltoall);
167   MPICollToCollTypes.push_back(IdentInfo_MPI_Alltoall);
168   MPIType.push_back(IdentInfo_MPI_Alltoall);
169   assert(IdentInfo_MPI_Alltoall);
170 
171   IdentInfo_MPI_Ialltoall = &ASTCtx.Idents.get("MPI_Ialltoall");
172   MPICollectiveTypes.push_back(IdentInfo_MPI_Ialltoall);
173   MPICollToCollTypes.push_back(IdentInfo_MPI_Ialltoall);
174   MPINonBlockingTypes.push_back(IdentInfo_MPI_Ialltoall);
175   MPIType.push_back(IdentInfo_MPI_Ialltoall);
176   assert(IdentInfo_MPI_Ialltoall);
177 }
178 
179 void MPIFunctionClassifier::initAdditionalIdentifiers(ASTContext &ASTCtx) {
180   IdentInfo_MPI_Comm_rank = &ASTCtx.Idents.get("MPI_Comm_rank");
181   MPIType.push_back(IdentInfo_MPI_Comm_rank);
182   assert(IdentInfo_MPI_Comm_rank);
183 
184   IdentInfo_MPI_Comm_size = &ASTCtx.Idents.get("MPI_Comm_size");
185   MPIType.push_back(IdentInfo_MPI_Comm_size);
186   assert(IdentInfo_MPI_Comm_size);
187 
188   IdentInfo_MPI_Wait = &ASTCtx.Idents.get("MPI_Wait");
189   MPIType.push_back(IdentInfo_MPI_Wait);
190   assert(IdentInfo_MPI_Wait);
191 
192   IdentInfo_MPI_Waitall = &ASTCtx.Idents.get("MPI_Waitall");
193   MPIType.push_back(IdentInfo_MPI_Waitall);
194   assert(IdentInfo_MPI_Waitall);
195 
196   IdentInfo_MPI_Barrier = &ASTCtx.Idents.get("MPI_Barrier");
197   MPICollectiveTypes.push_back(IdentInfo_MPI_Barrier);
198   MPIType.push_back(IdentInfo_MPI_Barrier);
199   assert(IdentInfo_MPI_Barrier);
200 }
201 
202 // general identifiers
203 bool MPIFunctionClassifier::isMPIType(const IdentifierInfo *IdentInfo) const {
204   return llvm::is_contained(MPIType, IdentInfo);
205 }
206 
207 bool MPIFunctionClassifier::isNonBlockingType(
208     const IdentifierInfo *IdentInfo) const {
209   return llvm::is_contained(MPINonBlockingTypes, IdentInfo);
210 }
211 
212 // point-to-point identifiers
213 bool MPIFunctionClassifier::isPointToPointType(
214     const IdentifierInfo *IdentInfo) const {
215   return llvm::is_contained(MPIPointToPointTypes, IdentInfo);
216 }
217 
218 // collective identifiers
219 bool MPIFunctionClassifier::isCollectiveType(
220     const IdentifierInfo *IdentInfo) const {
221   return llvm::is_contained(MPICollectiveTypes, IdentInfo);
222 }
223 
224 bool MPIFunctionClassifier::isCollToColl(
225     const IdentifierInfo *IdentInfo) const {
226   return llvm::is_contained(MPICollToCollTypes, IdentInfo);
227 }
228 
229 bool MPIFunctionClassifier::isScatterType(
230     const IdentifierInfo *IdentInfo) const {
231   return IdentInfo == IdentInfo_MPI_Scatter ||
232          IdentInfo == IdentInfo_MPI_Iscatter;
233 }
234 
235 bool MPIFunctionClassifier::isGatherType(
236     const IdentifierInfo *IdentInfo) const {
237   return IdentInfo == IdentInfo_MPI_Gather ||
238          IdentInfo == IdentInfo_MPI_Igather ||
239          IdentInfo == IdentInfo_MPI_Allgather ||
240          IdentInfo == IdentInfo_MPI_Iallgather;
241 }
242 
243 bool MPIFunctionClassifier::isAllgatherType(
244     const IdentifierInfo *IdentInfo) const {
245   return IdentInfo == IdentInfo_MPI_Allgather ||
246          IdentInfo == IdentInfo_MPI_Iallgather;
247 }
248 
249 bool MPIFunctionClassifier::isAlltoallType(
250     const IdentifierInfo *IdentInfo) const {
251   return IdentInfo == IdentInfo_MPI_Alltoall ||
252          IdentInfo == IdentInfo_MPI_Ialltoall;
253 }
254 
255 bool MPIFunctionClassifier::isBcastType(const IdentifierInfo *IdentInfo) const {
256   return IdentInfo == IdentInfo_MPI_Bcast || IdentInfo == IdentInfo_MPI_Ibcast;
257 }
258 
259 bool MPIFunctionClassifier::isReduceType(
260     const IdentifierInfo *IdentInfo) const {
261   return IdentInfo == IdentInfo_MPI_Reduce ||
262          IdentInfo == IdentInfo_MPI_Ireduce ||
263          IdentInfo == IdentInfo_MPI_Allreduce ||
264          IdentInfo == IdentInfo_MPI_Iallreduce;
265 }
266 
267 // additional identifiers
268 bool MPIFunctionClassifier::isMPI_Wait(const IdentifierInfo *IdentInfo) const {
269   return IdentInfo == IdentInfo_MPI_Wait;
270 }
271 
272 bool MPIFunctionClassifier::isMPI_Waitall(
273     const IdentifierInfo *IdentInfo) const {
274   return IdentInfo == IdentInfo_MPI_Waitall;
275 }
276 
277 bool MPIFunctionClassifier::isWaitType(const IdentifierInfo *IdentInfo) const {
278   return IdentInfo == IdentInfo_MPI_Wait || IdentInfo == IdentInfo_MPI_Waitall;
279 }
280 
281 } // end of namespace: mpi
282 } // end of namespace: ento
283 } // end of namespace: clang
284