Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Common/visit.h ----------------------------*- 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// common::visit() is a drop-in replacement for std::visit() that reduces both
10// compiler build time and compiler execution time modestly, and reduces
11// compiler build memory requirements significantly (overall & maximum).
12// It does not require redefinition of std::variant<>.
13//
14// The C++ standard mandates that std::visit be O(1), but most variants are
15// small and O(logN) is faster in practice to compile and execute, avoiding
16// the need to build a dispatch table.
17//
18// Define FLANG_USE_STD_VISIT to avoid this code and make common::visit() an
19// alias for ::std::visit().
20
21#ifndef FORTRAN_COMMON_VISIT_H_
22#define FORTRAN_COMMON_VISIT_H_
23
24#include "variant.h"
25#include "flang/Common/api-attrs.h"
26#include <type_traits>
27
28namespace Fortran::common {
29namespace log2visit {
30
31template <std::size_t LOW, std::size_t HIGH, typename RESULT, typename VISITOR,
32 typename... VARIANT>
33inline RT_API_ATTRS RESULT Log2VisitHelper(
34 VISITOR &&visitor, std::size_t which, VARIANT &&...u) {
35 if constexpr (LOW + 7 >= HIGH) {
36 switch (which - LOW) {
37#define VISIT_CASE_N(N) \
38 case N: \
39 if constexpr (LOW + N <= HIGH) { \
40 return visitor(std::get<(LOW + N)>(std::forward<VARIANT>(u))...); \
41 }
42 VISIT_CASE_N(1)
43 VISIT_CASE_N(2)
44 VISIT_CASE_N(3)
45 VISIT_CASE_N(4)
46 VISIT_CASE_N(5)
47 VISIT_CASE_N(6)
48 VISIT_CASE_N(7)
49#undef VISIT_CASE_N
50 }
51 return visitor(std::get<LOW>(std::forward<VARIANT>(u))...);
52 } else {
53 static constexpr std::size_t mid{(HIGH + LOW) / 2};
54 if (which <= mid) {
55 return Log2VisitHelper<LOW, mid, RESULT>(
56 std::forward<VISITOR>(visitor), which, std::forward<VARIANT>(u)...);
57 } else {
58 return Log2VisitHelper<(mid + 1), HIGH, RESULT>(
59 std::forward<VISITOR>(visitor), which, std::forward<VARIANT>(u)...);
60 }
61 }
62}
63
64template <typename VISITOR, typename... VARIANT>
65inline RT_API_ATTRS auto visit(VISITOR &&visitor, VARIANT &&...u)
66 -> decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...)) {
67 using Result = decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...));
68 if constexpr (sizeof...(u) == 1) {
69 static constexpr std::size_t high{
70 (std::variant_size_v<std::decay_t<decltype(u)>> * ...) - 1};
71 return Log2VisitHelper<0, high, Result>(std::forward<VISITOR>(visitor),
72 u.index()..., std::forward<VARIANT>(u)...);
73 } else {
74 // TODO: figure out how to do multiple variant arguments
75 return ::std::visit(
76 std::forward<VISITOR>(visitor), std::forward<VARIANT>(u)...);
77 }
78}
79
80} // namespace log2visit
81
82// Some versions of clang have bugs that cause compilation to hang
83// on these templates. MSVC and older GCC versions may work but are
84// not well tested. So enable only for GCC 9 and better.
85#if __GNUC__ < 9
86#define FLANG_USE_STD_VISIT
87#endif
88
89#ifdef FLANG_USE_STD_VISIT
90using ::std::visit;
91#else
92using Fortran::common::log2visit::visit;
93#endif
94
95} // namespace Fortran::common
96#endif // FORTRAN_COMMON_VISIT_H_
97

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Common/visit.h