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
17namespace clang {
18namespace ento {
19namespace mpi {
20
21void MPIFunctionClassifier::identifierInit(ASTContext &ASTCtx) {
22  // Initialize function identifiers.
23  initPointToPointIdentifiers(ASTCtx);
24  initCollectiveIdentifiers(ASTCtx);
25  initAdditionalIdentifiers(ASTCtx);
26}
27
28void 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
85void 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
179void 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
203bool MPIFunctionClassifier::isMPIType(const IdentifierInfo *IdentInfo) const {
204  return llvm::is_contained(MPIType, IdentInfo);
205}
206
207bool MPIFunctionClassifier::isNonBlockingType(
208    const IdentifierInfo *IdentInfo) const {
209  return llvm::is_contained(MPINonBlockingTypes, IdentInfo);
210}
211
212// point-to-point identifiers
213bool MPIFunctionClassifier::isPointToPointType(
214    const IdentifierInfo *IdentInfo) const {
215  return llvm::is_contained(MPIPointToPointTypes, IdentInfo);
216}
217
218// collective identifiers
219bool MPIFunctionClassifier::isCollectiveType(
220    const IdentifierInfo *IdentInfo) const {
221  return llvm::is_contained(MPICollectiveTypes, IdentInfo);
222}
223
224bool MPIFunctionClassifier::isCollToColl(
225    const IdentifierInfo *IdentInfo) const {
226  return llvm::is_contained(MPICollToCollTypes, IdentInfo);
227}
228
229bool MPIFunctionClassifier::isScatterType(
230    const IdentifierInfo *IdentInfo) const {
231  return IdentInfo == IdentInfo_MPI_Scatter ||
232         IdentInfo == IdentInfo_MPI_Iscatter;
233}
234
235bool 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
243bool MPIFunctionClassifier::isAllgatherType(
244    const IdentifierInfo *IdentInfo) const {
245  return IdentInfo == IdentInfo_MPI_Allgather ||
246         IdentInfo == IdentInfo_MPI_Iallgather;
247}
248
249bool MPIFunctionClassifier::isAlltoallType(
250    const IdentifierInfo *IdentInfo) const {
251  return IdentInfo == IdentInfo_MPI_Alltoall ||
252         IdentInfo == IdentInfo_MPI_Ialltoall;
253}
254
255bool MPIFunctionClassifier::isBcastType(const IdentifierInfo *IdentInfo) const {
256  return IdentInfo == IdentInfo_MPI_Bcast || IdentInfo == IdentInfo_MPI_Ibcast;
257}
258
259bool 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
268bool MPIFunctionClassifier::isMPI_Wait(const IdentifierInfo *IdentInfo) const {
269  return IdentInfo == IdentInfo_MPI_Wait;
270}
271
272bool MPIFunctionClassifier::isMPI_Waitall(
273    const IdentifierInfo *IdentInfo) const {
274  return IdentInfo == IdentInfo_MPI_Waitall;
275}
276
277bool 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