FLANG
Utils.h
1//===-- Lower/Support/Utils.h -- utilities ----------------------*- 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// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FORTRAN_LOWER_SUPPORT_UTILS_H
14#define FORTRAN_LOWER_SUPPORT_UTILS_H
15
16#include "flang/Common/indirection.h"
17#include "flang/Parser/char-block.h"
18#include "flang/Semantics/tools.h"
19#include "mlir/Dialect/Arith/IR/Arith.h"
20#include "mlir/Dialect/Func/IR/FuncOps.h"
21#include "mlir/IR/BuiltinAttributes.h"
22#include "llvm/ADT/StringRef.h"
23#include <cstdint>
24
25namespace Fortran::lower {
27} // end namespace Fortran::lower
28
29//===----------------------------------------------------------------------===//
30// Small inline helper functions to deal with repetitive, clumsy conversions.
31//===----------------------------------------------------------------------===//
32
34inline llvm::StringRef toStringRef(const Fortran::parser::CharBlock &cb) {
35 return {cb.begin(), cb.size()};
36}
37
39template <typename A>
40const A &removeIndirection(const A &a) {
41 return a;
42}
43template <typename A>
44const A &removeIndirection(const Fortran::common::Indirection<A> &a) {
45 return a.value();
46}
47
49template <typename A>
50static Fortran::lower::SomeExpr toEvExpr(const A &x) {
51 return Fortran::evaluate::AsGenericExpr(Fortran::common::Clone(x));
52}
53
54template <Fortran::common::TypeCategory FROM>
55static Fortran::lower::SomeExpr ignoreEvConvert(
58 FROM> &x) {
59 return toEvExpr(x.left());
60}
61template <typename A>
62static Fortran::lower::SomeExpr ignoreEvConvert(const A &x) {
63 return toEvExpr(x);
64}
65
71 Fortran::common::TypeCategory::Integer, 8>> &x) {
72 return Fortran::common::visit(
73 [](const auto &v) { return ignoreEvConvert(v); }, x.u);
74}
75
78template <typename A>
79A flatZip(const A &container1, const A &container2) {
80 assert(container1.size() == container2.size());
81 A result;
82 for (auto [e1, e2] : llvm::zip(container1, container2)) {
83 result.emplace_back(e1);
84 result.emplace_back(e2);
85 }
86 return result;
87}
88
89namespace Fortran::lower {
90// Fortran::evaluate::Expr are functional values organized like an AST. A
91// Fortran::evaluate::Expr is meant to be moved and cloned. Using the front end
92// tools can often cause copies and extra wrapper classes to be added to any
93// Fortran::evaluate::Expr. These values should not be assumed or relied upon to
94// have an *object* identity. They are deeply recursive, irregular structures
95// built from a large number of classes which do not use inheritance and
96// necessitate a large volume of boilerplate code as a result.
97//
98// Contrastingly, LLVM data structures make ubiquitous assumptions about an
99// object's identity via pointers to the object. An object's location in memory
100// is thus very often an identifying relation.
101
102// This class defines a hash computation of a Fortran::evaluate::Expr tree value
103// so it can be used with llvm::DenseMap. The Fortran::evaluate::Expr need not
104// have the same address.
106public:
107 // A Se::Symbol is the only part of an Fortran::evaluate::Expr with an
108 // identity property.
109 static unsigned getHashValue(const Fortran::semantics::Symbol &x) {
110 return static_cast<unsigned>(reinterpret_cast<std::intptr_t>(&x));
111 }
112 template <typename A, bool COPY>
113 static unsigned getHashValue(const Fortran::common::Indirection<A, COPY> &x) {
114 return getHashValue(x.value());
115 }
116 template <typename A>
117 static unsigned getHashValue(const std::optional<A> &x) {
118 if (x.has_value())
119 return getHashValue(x.value());
120 return 0u;
121 }
122 static unsigned getHashValue(const Fortran::evaluate::Subscript &x) {
123 return Fortran::common::visit(
124 [&](const auto &v) { return getHashValue(v); }, x.u);
125 }
126 static unsigned getHashValue(const Fortran::evaluate::Triplet &x) {
127 return getHashValue(x.lower()) - getHashValue(x.upper()) * 5u -
128 getHashValue(x.stride()) * 11u;
129 }
130 static unsigned getHashValue(const Fortran::evaluate::Component &x) {
131 return getHashValue(x.base()) * 83u - getHashValue(x.GetLastSymbol());
132 }
133 static unsigned getHashValue(const Fortran::evaluate::ArrayRef &x) {
134 unsigned subs = 1u;
135 for (const Fortran::evaluate::Subscript &v : x.subscript())
136 subs -= getHashValue(v);
137 return getHashValue(x.base()) * 89u - subs;
138 }
139 static unsigned getHashValue(const Fortran::evaluate::CoarrayRef &x) {
140 unsigned subs = 1u;
141 for (const Fortran::evaluate::Subscript &v : x.subscript())
142 subs -= getHashValue(v);
143 unsigned cosubs = 3u;
145 x.cosubscript())
146 cosubs -= getHashValue(v);
147 unsigned syms = 7u;
148 for (const Fortran::evaluate::SymbolRef &v : x.base())
149 syms += getHashValue(v);
150 return syms * 97u - subs - cosubs + getHashValue(x.stat()) + 257u +
151 getHashValue(x.team());
152 }
153 static unsigned getHashValue(const Fortran::evaluate::NamedEntity &x) {
154 if (x.IsSymbol())
155 return getHashValue(x.GetFirstSymbol()) * 11u;
156 return getHashValue(x.GetComponent()) * 13u;
157 }
158 static unsigned getHashValue(const Fortran::evaluate::DataRef &x) {
159 return Fortran::common::visit(
160 [&](const auto &v) { return getHashValue(v); }, x.u);
161 }
162 static unsigned getHashValue(const Fortran::evaluate::ComplexPart &x) {
163 return getHashValue(x.complex()) - static_cast<unsigned>(x.part());
164 }
165 template <Fortran::common::TypeCategory TC1, int KIND,
166 Fortran::common::TypeCategory TC2>
167 static unsigned getHashValue(
169 &x) {
170 return getHashValue(x.left()) - (static_cast<unsigned>(TC1) + 2u) -
171 (static_cast<unsigned>(KIND) + 5u);
172 }
173 template <int KIND>
174 static unsigned
175 getHashValue(const Fortran::evaluate::ComplexComponent<KIND> &x) {
176 return getHashValue(x.left()) -
177 (static_cast<unsigned>(x.isImaginaryPart) + 1u) * 3u;
178 }
179 template <typename T>
180 static unsigned getHashValue(const Fortran::evaluate::Parentheses<T> &x) {
181 return getHashValue(x.left()) * 17u;
182 }
183 template <Fortran::common::TypeCategory TC, int KIND>
184 static unsigned getHashValue(
186 return getHashValue(x.left()) - (static_cast<unsigned>(TC) + 5u) -
187 (static_cast<unsigned>(KIND) + 7u);
188 }
189 template <Fortran::common::TypeCategory TC, int KIND>
190 static unsigned getHashValue(
192 return (getHashValue(x.left()) + getHashValue(x.right())) * 23u +
193 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
194 }
195 template <Fortran::common::TypeCategory TC, int KIND>
196 static unsigned getHashValue(
198 return (getHashValue(x.left()) - getHashValue(x.right())) * 19u +
199 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
200 }
201 template <Fortran::common::TypeCategory TC, int KIND>
202 static unsigned getHashValue(
204 return (getHashValue(x.left()) + getHashValue(x.right())) * 29u +
205 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
206 }
207 template <Fortran::common::TypeCategory TC, int KIND>
208 static unsigned getHashValue(
210 return (getHashValue(x.left()) - getHashValue(x.right())) * 31u +
211 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
212 }
213 template <Fortran::common::TypeCategory TC, int KIND>
214 static unsigned getHashValue(
216 return (getHashValue(x.left()) - getHashValue(x.right())) * 37u +
217 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
218 }
219 template <Fortran::common::TypeCategory TC, int KIND>
220 static unsigned getHashValue(
222 return (getHashValue(x.left()) + getHashValue(x.right())) * 41u +
223 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND) +
224 static_cast<unsigned>(x.ordering) * 7u;
225 }
226 template <Fortran::common::TypeCategory TC, int KIND>
227 static unsigned getHashValue(
229 &x) {
230 return (getHashValue(x.left()) - getHashValue(x.right())) * 43u +
231 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND);
232 }
233 template <int KIND>
234 static unsigned
235 getHashValue(const Fortran::evaluate::ComplexConstructor<KIND> &x) {
236 return (getHashValue(x.left()) - getHashValue(x.right())) * 47u +
237 static_cast<unsigned>(KIND);
238 }
239 template <int KIND>
240 static unsigned getHashValue(const Fortran::evaluate::Concat<KIND> &x) {
241 return (getHashValue(x.left()) - getHashValue(x.right())) * 53u +
242 static_cast<unsigned>(KIND);
243 }
244 template <int KIND>
245 static unsigned getHashValue(const Fortran::evaluate::SetLength<KIND> &x) {
246 return (getHashValue(x.left()) - getHashValue(x.right())) * 59u +
247 static_cast<unsigned>(KIND);
248 }
249 static unsigned getHashValue(const Fortran::semantics::SymbolRef &sym) {
250 return getHashValue(sym.get());
251 }
252 static unsigned getHashValue(const Fortran::evaluate::Substring &x) {
253 return 61u *
254 Fortran::common::visit(
255 [&](const auto &p) { return getHashValue(p); }, x.parent()) -
256 getHashValue(x.lower()) - (getHashValue(x.lower()) + 1u);
257 }
258 static unsigned
259 getHashValue(const Fortran::evaluate::StaticDataObject::Pointer &x) {
260 return llvm::hash_value(x->name());
261 }
262 static unsigned getHashValue(const Fortran::evaluate::SpecificIntrinsic &x) {
263 return llvm::hash_value(x.name);
264 }
265 template <typename A>
266 static unsigned getHashValue(const Fortran::evaluate::Constant<A> &x) {
267 // FIXME: Should hash the content.
268 return 103u;
269 }
270 static unsigned getHashValue(const Fortran::evaluate::ActualArgument &x) {
271 if (const Fortran::evaluate::Symbol *sym = x.GetAssumedTypeDummy())
272 return getHashValue(*sym);
273 return getHashValue(*x.UnwrapExpr());
274 }
275 static unsigned
276 getHashValue(const Fortran::evaluate::ProcedureDesignator &x) {
277 return Fortran::common::visit(
278 [&](const auto &v) { return getHashValue(v); }, x.u);
279 }
280 static unsigned getHashValue(const Fortran::evaluate::ProcedureRef &x) {
281 unsigned args = 13u;
282 for (const std::optional<Fortran::evaluate::ActualArgument> &v :
283 x.arguments())
284 args -= getHashValue(v);
285 return getHashValue(x.proc()) * 101u - args;
286 }
287 template <typename A>
288 static unsigned
289 getHashValue(const Fortran::evaluate::ArrayConstructor<A> &x) {
290 // FIXME: hash the contents.
291 return 127u;
292 }
293 static unsigned getHashValue(const Fortran::evaluate::ImpliedDoIndex &x) {
294 return llvm::hash_value(toStringRef(x.name).str()) * 131u;
295 }
296 static unsigned getHashValue(const Fortran::evaluate::TypeParamInquiry &x) {
297 return getHashValue(x.base()) * 137u - getHashValue(x.parameter()) * 3u;
298 }
299 static unsigned getHashValue(const Fortran::evaluate::DescriptorInquiry &x) {
300 return getHashValue(x.base()) * 139u -
301 static_cast<unsigned>(x.field()) * 13u +
302 static_cast<unsigned>(x.dimension());
303 }
304 static unsigned
305 getHashValue(const Fortran::evaluate::StructureConstructor &x) {
306 // FIXME: hash the contents.
307 return 149u;
308 }
309 template <int KIND>
310 static unsigned getHashValue(const Fortran::evaluate::Not<KIND> &x) {
311 return getHashValue(x.left()) * 61u + static_cast<unsigned>(KIND);
312 }
313 template <int KIND>
314 static unsigned
315 getHashValue(const Fortran::evaluate::LogicalOperation<KIND> &x) {
316 unsigned result = getHashValue(x.left()) + getHashValue(x.right());
317 return result * 67u + static_cast<unsigned>(x.logicalOperator) * 5u;
318 }
319 template <Fortran::common::TypeCategory TC, int KIND>
320 static unsigned getHashValue(
322 &x) {
323 return (getHashValue(x.left()) + getHashValue(x.right())) * 71u +
324 static_cast<unsigned>(TC) + static_cast<unsigned>(KIND) +
325 static_cast<unsigned>(x.opr) * 11u;
326 }
327 template <typename A>
328 static unsigned getHashValue(const Fortran::evaluate::Expr<A> &x) {
329 return Fortran::common::visit(
330 [&](const auto &v) { return getHashValue(v); }, x.u);
331 }
332 static unsigned getHashValue(
334 return Fortran::common::visit(
335 [&](const auto &v) { return getHashValue(v); }, x.u);
336 }
337 template <typename A>
338 static unsigned getHashValue(const Fortran::evaluate::Designator<A> &x) {
339 return Fortran::common::visit(
340 [&](const auto &v) { return getHashValue(v); }, x.u);
341 }
342 template <int BITS>
343 static unsigned
344 getHashValue(const Fortran::evaluate::value::Integer<BITS> &x) {
345 return static_cast<unsigned>(x.ToSInt());
346 }
347 static unsigned getHashValue(const Fortran::evaluate::NullPointer &x) {
348 return ~179u;
349 }
350};
351
352// Define the is equals test for using Fortran::evaluate::Expr values with
353// llvm::DenseMap.
355public:
356 // A Se::Symbol is the only part of an Fortran::evaluate::Expr with an
357 // identity property.
358 static bool isEqual(const Fortran::semantics::Symbol &x,
360 return isEqual(&x, &y);
361 }
362 static bool isEqual(const Fortran::semantics::Symbol *x,
364 return x == y;
365 }
366 template <typename A, bool COPY>
367 static bool isEqual(const Fortran::common::Indirection<A, COPY> &x,
369 return isEqual(x.value(), y.value());
370 }
371 template <typename A>
372 static bool isEqual(const std::optional<A> &x, const std::optional<A> &y) {
373 if (x.has_value() && y.has_value())
374 return isEqual(x.value(), y.value());
375 return !x.has_value() && !y.has_value();
376 }
377 template <typename A>
378 static bool isEqual(const std::vector<A> &x, const std::vector<A> &y) {
379 if (x.size() != y.size())
380 return false;
381 const std::size_t size = x.size();
382 for (std::remove_const_t<decltype(size)> i = 0; i < size; ++i)
383 if (!isEqual(x[i], y[i]))
384 return false;
385 return true;
386 }
387 static bool isEqual(const Fortran::evaluate::Subscript &x,
389 return Fortran::common::visit(
390 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
391 }
392 static bool isEqual(const Fortran::evaluate::Triplet &x,
394 return isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper()) &&
395 isEqual(x.stride(), y.stride());
396 }
397 static bool isEqual(const Fortran::evaluate::Component &x,
399 return isEqual(x.base(), y.base()) &&
400 isEqual(x.GetLastSymbol(), y.GetLastSymbol());
401 }
402 static bool isEqual(const Fortran::evaluate::ArrayRef &x,
404 return isEqual(x.base(), y.base()) && isEqual(x.subscript(), y.subscript());
405 }
406 static bool isEqual(const Fortran::evaluate::CoarrayRef &x,
408 return isEqual(x.base(), y.base()) &&
409 isEqual(x.subscript(), y.subscript()) &&
410 isEqual(x.cosubscript(), y.cosubscript()) &&
411 isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team());
412 }
413 static bool isEqual(const Fortran::evaluate::NamedEntity &x,
415 if (x.IsSymbol() && y.IsSymbol())
416 return isEqual(x.GetFirstSymbol(), y.GetFirstSymbol());
417 return !x.IsSymbol() && !y.IsSymbol() &&
418 isEqual(x.GetComponent(), y.GetComponent());
419 }
420 static bool isEqual(const Fortran::evaluate::DataRef &x,
422 return Fortran::common::visit(
423 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
424 }
425 static bool isEqual(const Fortran::evaluate::ComplexPart &x,
427 return isEqual(x.complex(), y.complex()) && x.part() == y.part();
428 }
429 template <typename A, Fortran::common::TypeCategory TC2>
430 static bool isEqual(const Fortran::evaluate::Convert<A, TC2> &x,
432 return isEqual(x.left(), y.left());
433 }
434 template <int KIND>
435 static bool isEqual(const Fortran::evaluate::ComplexComponent<KIND> &x,
437 return isEqual(x.left(), y.left()) &&
438 x.isImaginaryPart == y.isImaginaryPart;
439 }
440 template <typename T>
441 static bool isEqual(const Fortran::evaluate::Parentheses<T> &x,
443 return isEqual(x.left(), y.left());
444 }
445 template <typename A>
446 static bool isEqual(const Fortran::evaluate::Negate<A> &x,
448 return isEqual(x.left(), y.left());
449 }
450 template <typename A>
451 static bool isBinaryEqual(const A &x, const A &y) {
452 return isEqual(x.left(), y.left()) && isEqual(x.right(), y.right());
453 }
454 template <typename A>
455 static bool isEqual(const Fortran::evaluate::Add<A> &x,
456 const Fortran::evaluate::Add<A> &y) {
457 return isBinaryEqual(x, y);
458 }
459 template <typename A>
460 static bool isEqual(const Fortran::evaluate::Subtract<A> &x,
462 return isBinaryEqual(x, y);
463 }
464 template <typename A>
465 static bool isEqual(const Fortran::evaluate::Multiply<A> &x,
467 return isBinaryEqual(x, y);
468 }
469 template <typename A>
470 static bool isEqual(const Fortran::evaluate::Divide<A> &x,
472 return isBinaryEqual(x, y);
473 }
474 template <typename A>
475 static bool isEqual(const Fortran::evaluate::Power<A> &x,
477 return isBinaryEqual(x, y);
478 }
479 template <typename A>
480 static bool isEqual(const Fortran::evaluate::Extremum<A> &x,
482 return isBinaryEqual(x, y);
483 }
484 template <typename A>
485 static bool isEqual(const Fortran::evaluate::RealToIntPower<A> &x,
487 return isBinaryEqual(x, y);
488 }
489 template <int KIND>
490 static bool isEqual(const Fortran::evaluate::ComplexConstructor<KIND> &x,
492 return isBinaryEqual(x, y);
493 }
494 template <int KIND>
495 static bool isEqual(const Fortran::evaluate::Concat<KIND> &x,
497 return isBinaryEqual(x, y);
498 }
499 template <int KIND>
500 static bool isEqual(const Fortran::evaluate::SetLength<KIND> &x,
502 return isBinaryEqual(x, y);
503 }
504 static bool isEqual(const Fortran::semantics::SymbolRef &x,
506 return isEqual(x.get(), y.get());
507 }
508 static bool isEqual(const Fortran::evaluate::Substring &x,
510 return Fortran::common::visit(
511 [&](const auto &p, const auto &q) { return isEqual(p, q); },
512 x.parent(), y.parent()) &&
513 isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper());
514 }
515 static bool isEqual(const Fortran::evaluate::StaticDataObject::Pointer &x,
516 const Fortran::evaluate::StaticDataObject::Pointer &y) {
517 return x->name() == y->name();
518 }
519 static bool isEqual(const Fortran::evaluate::SpecificIntrinsic &x,
521 return x.name == y.name;
522 }
523 template <typename A>
524 static bool isEqual(const Fortran::evaluate::Constant<A> &x,
526 return x == y;
527 }
528 static bool isEqual(const Fortran::evaluate::ActualArgument &x,
530 if (const Fortran::evaluate::Symbol *xs = x.GetAssumedTypeDummy()) {
531 if (const Fortran::evaluate::Symbol *ys = y.GetAssumedTypeDummy())
532 return isEqual(*xs, *ys);
533 return false;
534 }
535 return !y.GetAssumedTypeDummy() &&
536 isEqual(*x.UnwrapExpr(), *y.UnwrapExpr());
537 }
538 static bool isEqual(const Fortran::evaluate::ProcedureDesignator &x,
540 return Fortran::common::visit(
541 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
542 }
543 static bool isEqual(const Fortran::evaluate::ProcedureRef &x,
545 return isEqual(x.proc(), y.proc()) && isEqual(x.arguments(), y.arguments());
546 }
547 template <typename A>
548 static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
550 llvm::report_fatal_error("not implemented");
551 }
552 static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
554 return toStringRef(x.name) == toStringRef(y.name);
555 }
556 static bool isEqual(const Fortran::evaluate::TypeParamInquiry &x,
558 return isEqual(x.base(), y.base()) && isEqual(x.parameter(), y.parameter());
559 }
560 static bool isEqual(const Fortran::evaluate::DescriptorInquiry &x,
562 return isEqual(x.base(), y.base()) && x.field() == y.field() &&
563 x.dimension() == y.dimension();
564 }
565 static bool isEqual(const Fortran::evaluate::StructureConstructor &x,
567 const auto &xValues = x.values();
568 const auto &yValues = y.values();
569 if (xValues.size() != yValues.size())
570 return false;
571 if (x.derivedTypeSpec() != y.derivedTypeSpec())
572 return false;
573 for (const auto &[xSymbol, xValue] : xValues) {
574 auto yIt = yValues.find(xSymbol);
575 // This should probably never happen, since the derived type
576 // should be the same.
577 if (yIt == yValues.end())
578 return false;
579 if (!isEqual(xValue, yIt->second))
580 return false;
581 }
582 return true;
583 }
584 template <int KIND>
585 static bool isEqual(const Fortran::evaluate::Not<KIND> &x,
587 return isEqual(x.left(), y.left());
588 }
589 template <int KIND>
590 static bool isEqual(const Fortran::evaluate::LogicalOperation<KIND> &x,
592 return isEqual(x.left(), y.left()) && isEqual(x.right(), y.right());
593 }
594 template <typename A>
595 static bool isEqual(const Fortran::evaluate::Relational<A> &x,
597 return isEqual(x.left(), y.left()) && isEqual(x.right(), y.right());
598 }
599 template <typename A>
600 static bool isEqual(const Fortran::evaluate::Expr<A> &x,
602 return Fortran::common::visit(
603 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
604 }
605 static bool
608 return Fortran::common::visit(
609 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
610 }
611 template <typename A>
612 static bool isEqual(const Fortran::evaluate::Designator<A> &x,
614 return Fortran::common::visit(
615 [&](const auto &v, const auto &w) { return isEqual(v, w); }, x.u, y.u);
616 }
617 template <int BITS>
618 static bool isEqual(const Fortran::evaluate::value::Integer<BITS> &x,
619 const Fortran::evaluate::value::Integer<BITS> &y) {
620 return x == y;
621 }
622 static bool isEqual(const Fortran::evaluate::NullPointer &x,
624 return true;
625 }
626 template <typename A, typename B,
627 std::enable_if_t<!std::is_same_v<A, B>, bool> = true>
628 static bool isEqual(const A &, const B &) {
629 return false;
630 }
631};
632
633static inline unsigned getHashValue(const Fortran::lower::SomeExpr *x) {
634 return HashEvaluateExpr::getHashValue(*x);
635}
636
637static bool isEqual(const Fortran::lower::SomeExpr *x,
638 const Fortran::lower::SomeExpr *y);
639} // end namespace Fortran::lower
640
641// DenseMapInfo for pointers to Fortran::lower::SomeExpr.
642namespace llvm {
643template <>
644struct DenseMapInfo<const Fortran::lower::SomeExpr *> {
645 static inline const Fortran::lower::SomeExpr *getEmptyKey() {
646 return reinterpret_cast<Fortran::lower::SomeExpr *>(~0);
647 }
648 static inline const Fortran::lower::SomeExpr *getTombstoneKey() {
649 return reinterpret_cast<Fortran::lower::SomeExpr *>(~0 - 1);
650 }
651 static unsigned getHashValue(const Fortran::lower::SomeExpr *v) {
652 return Fortran::lower::getHashValue(v);
653 }
654 static bool isEqual(const Fortran::lower::SomeExpr *lhs,
655 const Fortran::lower::SomeExpr *rhs) {
656 return Fortran::lower::isEqual(lhs, rhs);
657 }
658};
659} // namespace llvm
660
661namespace Fortran::lower {
662static inline bool isEqual(const Fortran::lower::SomeExpr *x,
663 const Fortran::lower::SomeExpr *y) {
664 const auto *empty =
665 llvm::DenseMapInfo<const Fortran::lower::SomeExpr *>::getEmptyKey();
666 const auto *tombstone =
667 llvm::DenseMapInfo<const Fortran::lower::SomeExpr *>::getTombstoneKey();
668 if (x == empty || y == empty || x == tombstone || y == tombstone)
669 return x == y;
670 return x == y || IsEqualEvaluateExpr::isEqual(*x, *y);
671}
672} // end namespace Fortran::lower
673
674#endif // FORTRAN_LOWER_SUPPORT_UTILS_H
Definition: indirection.h:31
Definition: expression.h:466
Definition: variable.h:208
Definition: variable.h:255
Definition: variable.h:369
Definition: variable.h:74
Definition: constant.h:141
Definition: variable.h:425
Definition: variable.h:393
Definition: common.h:213
Definition: variable.h:104
Definition: call.h:232
Definition: expression.h:656
Definition: expression.h:740
Definition: variable.h:316
Definition: variable.h:163
Definition: variable.h:139
Definition: type.h:56
Definition: Utils.h:105
Definition: char-block.h:28
Definition: symbol.h:712
Definition: AbstractConverter.h:59
Definition: bit-population-count.h:20
Definition: expression.h:296
Definition: expression.h:257
Definition: expression.h:357
Definition: expression.h:368
Definition: expression.h:211
Definition: variable.h:300
Definition: expression.h:317
Definition: expression.h:340
Definition: expression.h:396
Definition: expression.h:379
Definition: expression.h:310
Definition: expression.h:247
Definition: expression.h:272
Definition: expression.h:827
Definition: expression.h:229
Definition: expression.h:324
Definition: expression.h:332
Definition: expression.h:286
Definition: variable.h:194
Definition: expression.h:303