Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/Visitors.h
Line
Count
Source (jump to first uncovered line)
1
//===- Visitors.h - Utilities for visiting operations -----------*- 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
// This file defines utilities for walking and visiting operations.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef MLIR_IR_VISITORS_H
14
#define MLIR_IR_VISITORS_H
15
16
#include "mlir/Support/LLVM.h"
17
#include "mlir/Support/LogicalResult.h"
18
#include "llvm/ADT/STLExtras.h"
19
20
namespace mlir {
21
class Diagnostic;
22
class InFlightDiagnostic;
23
class Operation;
24
25
/// A utility result that is used to signal if a walk method should be
26
/// interrupted or advance.
27
class WalkResult {
28
  enum ResultEnum { Interrupt, Advance } result;
29
30
public:
31
0
  WalkResult(ResultEnum result) : result(result) {}
32
33
  /// Allow LogicalResult to interrupt the walk on failure.
34
  WalkResult(LogicalResult result)
35
0
      : result(failed(result) ? Interrupt : Advance) {}
36
37
  /// Allow diagnostics to interrupt the walk.
38
0
  WalkResult(Diagnostic &&) : result(Interrupt) {}
39
0
  WalkResult(InFlightDiagnostic &&) : result(Interrupt) {}
40
41
0
  bool operator==(const WalkResult &rhs) const { return result == rhs.result; }
42
43
0
  static WalkResult interrupt() { return {Interrupt}; }
44
0
  static WalkResult advance() { return {Advance}; }
45
46
  /// Returns if the walk was interrupted.
47
0
  bool wasInterrupted() const { return result == Interrupt; }
48
};
49
50
namespace detail {
51
/// Helper templates to deduce the first argument of a callback parameter.
52
template <typename Ret, typename Arg> Arg first_argument_type(Ret (*)(Arg));
53
template <typename Ret, typename F, typename Arg>
54
Arg first_argument_type(Ret (F::*)(Arg));
55
template <typename Ret, typename F, typename Arg>
56
Arg first_argument_type(Ret (F::*)(Arg) const);
57
template <typename F>
58
decltype(first_argument_type(&F::operator())) first_argument_type(F);
59
60
/// Type definition of the first argument to the given callable 'T'.
61
template <typename T>
62
using first_argument = decltype(first_argument_type(std::declval<T>()));
63
64
/// Walk all of the operations nested under and including the given operation.
65
void walkOperations(Operation *op, function_ref<void(Operation *op)> callback);
66
67
/// Walk all of the operations nested under and including the given operation.
68
/// This methods walks operations until an interrupt result is returned by the
69
/// callback.
70
WalkResult walkOperations(Operation *op,
71
                          function_ref<WalkResult(Operation *op)> callback);
72
73
// Below are a set of functions to walk nested operations. Users should favor
74
// the direct `walk` methods on the IR classes(Operation/Block/etc) over these
75
// methods. They are also templated to allow for statically dispatching based
76
// upon the type of the callback function.
77
78
/// Walk all of the operations nested under and including the given operation.
79
/// This method is selected for callbacks that operation on Operation*.
80
///
81
/// Example:
82
///   op->walk([](Operation *op) { ... });
83
template <
84
    typename FuncTy, typename ArgT = detail::first_argument<FuncTy>,
85
    typename RetT = decltype(std::declval<FuncTy>()(std::declval<ArgT>()))>
86
typename std::enable_if<std::is_same<ArgT, Operation *>::value, RetT>::type
87
0
walkOperations(Operation *op, FuncTy &&callback) {
88
0
  return detail::walkOperations(op, function_ref<RetT(ArgT)>(callback));
89
0
}
Unexecuted instantiation: Ops.cpp:_ZN4mlir6detail14walkOperationsIRZL6verifyNS_18GenericAtomicRMWOpEE4$_24PNS_9OperationENS_10WalkResultEEENSt9enable_ifIXsr3std7is_sameIT0_S6_EE5valueET1_E4typeES6_OT_
Unexecuted instantiation: AsmPrinter.cpp:_ZN4mlir6detail14walkOperationsIZN12_GLOBAL__N_110AliasState10initializeEPNS_9OperationERNS_26DialectInterfaceCollectionINS_21OpAsmDialectInterfaceEEEE3$_2S5_vEENSt9enable_ifIXsr3std7is_sameIT0_S5_EE5valueET1_E4typeES5_OT_
Unexecuted instantiation: Region.cpp:_ZN4mlir6detail14walkOperationsIRZNS_6Region9cloneIntoEPS2_N4llvm14ilist_iteratorINS4_12ilist_detail12node_optionsINS_5BlockELb1ELb0EvEELb0ELb0EEERNS_20BlockAndValueMappingEE3$_0PNS_9OperationEvEENSt9enable_ifIXsr3std7is_sameIT0_SG_EE5valueET1_E4typeESG_OT_
90
91
/// Walk all of the operations of type 'ArgT' nested under and including the
92
/// given operation. This method is selected for void returning callbacks that
93
/// operate on a specific derived operation type.
94
///
95
/// Example:
96
///   op->walk([](ReturnOp op) { ... });
97
template <
98
    typename FuncTy, typename ArgT = detail::first_argument<FuncTy>,
99
    typename RetT = decltype(std::declval<FuncTy>()(std::declval<ArgT>()))>
100
typename std::enable_if<!std::is_same<ArgT, Operation *>::value &&
101
                            std::is_same<RetT, void>::value,
102
                        RetT>::type
103
walkOperations(Operation *op, FuncTy &&callback) {
104
  auto wrapperFn = [&](Operation *op) {
105
    if (auto derivedOp = dyn_cast<ArgT>(op))
106
      callback(derivedOp);
107
  };
108
  return detail::walkOperations(op, function_ref<RetT(Operation *)>(wrapperFn));
109
}
110
111
/// Walk all of the operations of type 'ArgT' nested under and including the
112
/// given operation. This method is selected for WalkReturn returning
113
/// interruptible callbacks that operate on a specific derived operation type.
114
///
115
/// Example:
116
///   op->walk([](ReturnOp op) {
117
///     if (some_invariant)
118
///       return WalkResult::interrupt();
119
///     return WalkResult::advance();
120
///   });
121
template <
122
    typename FuncTy, typename ArgT = detail::first_argument<FuncTy>,
123
    typename RetT = decltype(std::declval<FuncTy>()(std::declval<ArgT>()))>
124
typename std::enable_if<!std::is_same<ArgT, Operation *>::value &&
125
                            std::is_same<RetT, WalkResult>::value,
126
                        RetT>::type
127
walkOperations(Operation *op, FuncTy &&callback) {
128
  auto wrapperFn = [&](Operation *op) {
129
    if (auto derivedOp = dyn_cast<ArgT>(op))
130
      return callback(derivedOp);
131
    return WalkResult::advance();
132
  };
133
  return detail::walkOperations(op, function_ref<RetT(Operation *)>(wrapperFn));
134
}
135
136
/// Utility to provide the return type of a templated walk method.
137
template <typename FnT>
138
using walkResultType = decltype(walkOperations(nullptr, std::declval<FnT>()));
139
} // end namespace detail
140
141
} // namespace mlir
142
143
#endif