| //===-- lib/runtime/findloc-total.cpp ---------------------------*- C++ -*-===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // Implements total FINDLOC for all required operand types and shapes and | |
| // result integer kinds. | |
| #include "findloc.h" | |
| namespace Fortran::runtime { | |
| extern "C" { | |
| RT_EXT_API_GROUP_BEGIN | |
| void RTDEF(Findloc)(Descriptor &result, const Descriptor &x, | |
| const Descriptor &target, int kind, const char *source, int line, | |
| const Descriptor *mask, bool back) { | |
| int rank{x.rank()}; | |
| SubscriptValue extent[1]{rank}; | |
| result.Establish(TypeCategory::Integer, kind, nullptr, 1, extent, | |
| CFI_attribute_allocatable); | |
| result.GetDimension(0).SetBounds(1, extent[0]); | |
| Terminator terminator{source, line}; | |
| if (int stat{result.Allocate(kNoAsyncObject)}) { | |
| terminator.Crash( | |
| "FINDLOC: could not allocate memory for result; STAT=%d", stat); | |
| } | |
| CheckIntegerKind(terminator, kind, "FINDLOC"); | |
| auto xType{x.type().GetCategoryAndKind()}; | |
| auto targetType{target.type().GetCategoryAndKind()}; | |
| RUNTIME_CHECK(terminator, xType.has_value() && targetType.has_value()); | |
| switch (xType->first) { | |
| case TypeCategory::Integer: | |
| case TypeCategory::Unsigned: | |
| ApplyIntegerKind< | |
| TotalNumericFindlocSource<TypeCategory::Integer>::template Functor, | |
| void>(xType->second, terminator, targetType->first, targetType->second, | |
| result, x, target, kind, 0, mask, back, terminator); | |
| break; | |
| case TypeCategory::Real: | |
| ApplyFloatingPointKind< | |
| TotalNumericFindlocSource<TypeCategory::Real>::template Functor, void>( | |
| xType->second, terminator, targetType->first, targetType->second, | |
| result, x, target, kind, 0, mask, back, terminator); | |
| break; | |
| case TypeCategory::Complex: | |
| ApplyFloatingPointKind< | |
| TotalNumericFindlocSource<TypeCategory::Complex>::template Functor, | |
| void>(xType->second, terminator, targetType->first, targetType->second, | |
| result, x, target, kind, 0, mask, back, terminator); | |
| break; | |
| case TypeCategory::Character: | |
| RUNTIME_CHECK(terminator, | |
| targetType->first == TypeCategory::Character && | |
| targetType->second == xType->second); | |
| ApplyCharacterKind<CharacterFindlocHelper, void>(xType->second, terminator, | |
| result, x, target, kind, mask, back, terminator); | |
| break; | |
| case TypeCategory::Logical: | |
| RUNTIME_CHECK(terminator, targetType->first == TypeCategory::Logical); | |
| LogicalFindlocHelper(result, x, target, kind, mask, back, terminator); | |
| break; | |
| default: | |
| terminator.Crash( | |
| "FINDLOC: bad data type code (%d) for array", x.type().raw()); | |
| } | |
| } | |
| RT_EXT_API_GROUP_END | |
| } // extern "C" | |
| } // namespace Fortran::runtime |