| //===- OMP.cpp ------ Collection of helpers for OpenMP --------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Frontend/OpenMP/OMP.h" |
| |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/StringSwitch.h" |
| #include "llvm/Support/ErrorHandling.h" |
| |
| #include <algorithm> |
| #include <iterator> |
| #include <type_traits> |
| |
| using namespace llvm; |
| using namespace llvm::omp; |
| |
| #define GEN_DIRECTIVES_IMPL |
| #include "llvm/Frontend/OpenMP/OMP.inc" |
| |
| namespace llvm::omp { |
| ArrayRef<Directive> getLeafConstructs(Directive D) { |
| auto Idx = static_cast<std::size_t>(D); |
| if (Idx >= Directive_enumSize) |
| return std::nullopt; |
| const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]]; |
| return ArrayRef(&Row[2], static_cast<int>(Row[1])); |
| } |
| |
| Directive getCompoundConstruct(ArrayRef<Directive> Parts) { |
| if (Parts.empty()) |
| return OMPD_unknown; |
| |
| // Parts don't have to be leafs, so expand them into leafs first. |
| // Store the expanded leafs in the same format as rows in the leaf |
| // table (generated by tablegen). |
| SmallVector<Directive> RawLeafs(2); |
| for (Directive P : Parts) { |
| ArrayRef<Directive> Ls = getLeafConstructs(P); |
| if (!Ls.empty()) |
| RawLeafs.append(Ls.begin(), Ls.end()); |
| else |
| RawLeafs.push_back(P); |
| } |
| |
| // RawLeafs will be used as key in the binary search. The search doesn't |
| // guarantee that the exact same entry will be found (since RawLeafs may |
| // not correspond to any compound directive). Because of that, we will |
| // need to compare the search result with the given set of leafs. |
| // Also, if there is only one leaf in the list, it corresponds to itself, |
| // no search is necessary. |
| auto GivenLeafs{ArrayRef<Directive>(RawLeafs).drop_front(2)}; |
| if (GivenLeafs.size() == 1) |
| return GivenLeafs.front(); |
| RawLeafs[1] = static_cast<Directive>(GivenLeafs.size()); |
| |
| auto Iter = std::lower_bound( |
| LeafConstructTable, LeafConstructTableEndDirective, |
| static_cast<std::decay_t<decltype(*LeafConstructTable)>>(RawLeafs.data()), |
| [](const llvm::omp::Directive *RowA, const llvm::omp::Directive *RowB) { |
| const auto *BeginA = &RowA[2]; |
| const auto *EndA = BeginA + static_cast<int>(RowA[1]); |
| const auto *BeginB = &RowB[2]; |
| const auto *EndB = BeginB + static_cast<int>(RowB[1]); |
| if (BeginA == EndA && BeginB == EndB) |
| return static_cast<int>(RowA[0]) < static_cast<int>(RowB[0]); |
| return std::lexicographical_compare(BeginA, EndA, BeginB, EndB); |
| }); |
| |
| if (Iter == std::end(LeafConstructTable)) |
| return OMPD_unknown; |
| |
| // Verify that we got a match. |
| Directive Found = (*Iter)[0]; |
| ArrayRef<Directive> FoundLeafs = getLeafConstructs(Found); |
| if (FoundLeafs == GivenLeafs) |
| return Found; |
| return OMPD_unknown; |
| } |
| } // namespace llvm::omp |