1a48e4168Speter klausler //===-- runtime/derived-api.cpp 2a48e4168Speter klausler //-----------------------------------------------===// 3a48e4168Speter klausler // 4a48e4168Speter klausler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5a48e4168Speter klausler // See https://llvm.org/LICENSE.txt for license information. 6a48e4168Speter klausler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7a48e4168Speter klausler // 8a48e4168Speter klausler //===----------------------------------------------------------------------===// 9a48e4168Speter klausler 10830c0b90SPeter Klausler #include "flang/Runtime/derived-api.h" 11a48e4168Speter klausler #include "derived.h" 12a48e4168Speter klausler #include "terminator.h" 13b4b23ff7SSlava Zakharin #include "tools.h" 14a48e4168Speter klausler #include "type-info.h" 15830c0b90SPeter Klausler #include "flang/Runtime/descriptor.h" 16a48e4168Speter klausler 17a48e4168Speter klausler namespace Fortran::runtime { 18a48e4168Speter klausler 19a48e4168Speter klausler extern "C" { 2076facde3SSlava Zakharin RT_EXT_API_GROUP_BEGIN 21a48e4168Speter klausler 22b4b23ff7SSlava Zakharin void RTDEF(Initialize)( 23a48e4168Speter klausler const Descriptor &descriptor, const char *sourceFile, int sourceLine) { 24a48e4168Speter klausler if (const DescriptorAddendum * addendum{descriptor.Addendum()}) { 25a48e4168Speter klausler if (const auto *derived{addendum->derivedType()}) { 26a48e4168Speter klausler if (!derived->noInitializationNeeded()) { 27a48e4168Speter klausler Terminator terminator{sourceFile, sourceLine}; 28a48e4168Speter klausler Initialize(descriptor, *derived, terminator); 29a48e4168Speter klausler } 30a48e4168Speter klausler } 31a48e4168Speter klausler } 32a48e4168Speter klausler } 33a48e4168Speter klausler 34*1fcb6a97SLeandro Lupori void RTDEF(InitializeClone)(const Descriptor &clone, const Descriptor &orig, 35*1fcb6a97SLeandro Lupori const char *sourceFile, int sourceLine) { 36*1fcb6a97SLeandro Lupori if (const DescriptorAddendum * addendum{clone.Addendum()}) { 37*1fcb6a97SLeandro Lupori if (const auto *derived{addendum->derivedType()}) { 38*1fcb6a97SLeandro Lupori Terminator terminator{sourceFile, sourceLine}; 39*1fcb6a97SLeandro Lupori InitializeClone(clone, orig, *derived, terminator); 40*1fcb6a97SLeandro Lupori } 41*1fcb6a97SLeandro Lupori } 42*1fcb6a97SLeandro Lupori } 43*1fcb6a97SLeandro Lupori 44b4b23ff7SSlava Zakharin void RTDEF(Destroy)(const Descriptor &descriptor) { 45a48e4168Speter klausler if (const DescriptorAddendum * addendum{descriptor.Addendum()}) { 46a48e4168Speter klausler if (const auto *derived{addendum->derivedType()}) { 47a48e4168Speter klausler if (!derived->noDestructionNeeded()) { 48b21c24c3SPeter Klausler // TODO: Pass source file & line information to the API 49b21c24c3SPeter Klausler // so that a good Terminator can be passed 50b21c24c3SPeter Klausler Destroy(descriptor, true, *derived, nullptr); 51a48e4168Speter klausler } 52a48e4168Speter klausler } 53a48e4168Speter klausler } 54a48e4168Speter klausler } 55a48e4168Speter klausler 56b4b23ff7SSlava Zakharin void RTDEF(Finalize)( 57ab1db262SSlava Zakharin const Descriptor &descriptor, const char *sourceFile, int sourceLine) { 58ab1db262SSlava Zakharin if (const DescriptorAddendum * addendum{descriptor.Addendum()}) { 59ab1db262SSlava Zakharin if (const auto *derived{addendum->derivedType()}) { 60ab1db262SSlava Zakharin if (!derived->noFinalizationNeeded()) { 61ab1db262SSlava Zakharin Terminator terminator{sourceFile, sourceLine}; 62ab1db262SSlava Zakharin Finalize(descriptor, *derived, &terminator); 63ab1db262SSlava Zakharin } 64ab1db262SSlava Zakharin } 65ab1db262SSlava Zakharin } 66ab1db262SSlava Zakharin } 67ab1db262SSlava Zakharin 68b4b23ff7SSlava Zakharin bool RTDEF(ClassIs)( 698dfd8835SValentin Clement const Descriptor &descriptor, const typeInfo::DerivedType &derivedType) { 708dfd8835SValentin Clement if (const DescriptorAddendum * addendum{descriptor.Addendum()}) { 718dfd8835SValentin Clement if (const auto *derived{addendum->derivedType()}) { 728dfd8835SValentin Clement if (derived == &derivedType) { 738dfd8835SValentin Clement return true; 748dfd8835SValentin Clement } 758dfd8835SValentin Clement const typeInfo::DerivedType *parent{derived->GetParentType()}; 768dfd8835SValentin Clement while (parent) { 778dfd8835SValentin Clement if (parent == &derivedType) { 788dfd8835SValentin Clement return true; 798dfd8835SValentin Clement } 808dfd8835SValentin Clement parent = parent->GetParentType(); 818dfd8835SValentin Clement } 828dfd8835SValentin Clement } 838dfd8835SValentin Clement } 848dfd8835SValentin Clement return false; 858dfd8835SValentin Clement } 868dfd8835SValentin Clement 87b4b23ff7SSlava Zakharin static RT_API_ATTRS bool CompareDerivedTypeNames( 88b4b23ff7SSlava Zakharin const Descriptor &a, const Descriptor &b) { 894bb17511SValentin Clement if (a.raw().version == CFI_VERSION && 904bb17511SValentin Clement a.type() == TypeCode{TypeCategory::Character, 1} && 914bb17511SValentin Clement a.ElementBytes() > 0 && a.rank() == 0 && a.OffsetElement() != nullptr && 924bb17511SValentin Clement a.raw().version == CFI_VERSION && 934bb17511SValentin Clement b.type() == TypeCode{TypeCategory::Character, 1} && 944bb17511SValentin Clement b.ElementBytes() > 0 && b.rank() == 0 && b.OffsetElement() != nullptr && 954bb17511SValentin Clement a.ElementBytes() == b.ElementBytes() && 96b4b23ff7SSlava Zakharin Fortran::runtime::memcmp( 97b4b23ff7SSlava Zakharin a.OffsetElement(), b.OffsetElement(), a.ElementBytes()) == 0) { 984bb17511SValentin Clement return true; 994bb17511SValentin Clement } 1004bb17511SValentin Clement return false; 1014bb17511SValentin Clement } 1024bb17511SValentin Clement 103b4b23ff7SSlava Zakharin inline RT_API_ATTRS bool CompareDerivedType( 10487bd9461SValentin Clement const typeInfo::DerivedType *a, const typeInfo::DerivedType *b) { 10587bd9461SValentin Clement return a == b || CompareDerivedTypeNames(a->name(), b->name()); 10687bd9461SValentin Clement } 10787bd9461SValentin Clement 1088ebf4084SSlava Zakharin static RT_API_ATTRS const typeInfo::DerivedType *GetDerivedType( 109b4b23ff7SSlava Zakharin const Descriptor &desc) { 1104bb17511SValentin Clement if (const DescriptorAddendum * addendum{desc.Addendum()}) { 1114bb17511SValentin Clement if (const auto *derived{addendum->derivedType()}) { 1124bb17511SValentin Clement return derived; 1134bb17511SValentin Clement } 1144bb17511SValentin Clement } 1154bb17511SValentin Clement return nullptr; 1164bb17511SValentin Clement } 1174bb17511SValentin Clement 118b4b23ff7SSlava Zakharin bool RTDEF(SameTypeAs)(const Descriptor &a, const Descriptor &b) { 119dffd93b3SPeter Klausler auto aType{a.raw().type}; 120dffd93b3SPeter Klausler auto bType{b.raw().type}; 121dffd93b3SPeter Klausler if ((aType != CFI_type_struct && aType != CFI_type_other) || 122dffd93b3SPeter Klausler (bType != CFI_type_struct && bType != CFI_type_other)) { 123dffd93b3SPeter Klausler // If either type is intrinsic, they must match. 124dffd93b3SPeter Klausler return aType == bType; 125dffd93b3SPeter Klausler } else { 1264bb17511SValentin Clement const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)}; 1274bb17511SValentin Clement const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)}; 128188c02daSValentin Clement if (derivedTypeA == nullptr || derivedTypeB == nullptr) { 129dffd93b3SPeter Klausler // Unallocated/disassociated CLASS(*) never matches. 130188c02daSValentin Clement return false; 131dffd93b3SPeter Klausler } else if (derivedTypeA == derivedTypeB) { 1324bb17511SValentin Clement // Exact match of derived type. 1334bb17511SValentin Clement return true; 134dffd93b3SPeter Klausler } else { 135dffd93b3SPeter Klausler // Otherwise compare with the name. Note 16.29 kind type parameters are 136dffd93b3SPeter Klausler // not considered in the test. 137dffd93b3SPeter Klausler return CompareDerivedTypeNames( 138dffd93b3SPeter Klausler derivedTypeA->name(), derivedTypeB->name()); 1394bb17511SValentin Clement } 140dffd93b3SPeter Klausler } 1414bb17511SValentin Clement } 1424bb17511SValentin Clement 143b4b23ff7SSlava Zakharin bool RTDEF(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) { 144dffd93b3SPeter Klausler auto aType{a.raw().type}; 145dffd93b3SPeter Klausler auto moldType{mold.raw().type}; 146dffd93b3SPeter Klausler if ((aType != CFI_type_struct && aType != CFI_type_other) || 147dffd93b3SPeter Klausler (moldType != CFI_type_struct && moldType != CFI_type_other)) { 148dffd93b3SPeter Klausler // If either type is intrinsic, they must match. 149dffd93b3SPeter Klausler return aType == moldType; 150dffd93b3SPeter Klausler } else if (const typeInfo::DerivedType * 151dffd93b3SPeter Klausler derivedTypeMold{GetDerivedType(mold)}) { 15287bd9461SValentin Clement // If A is unlimited polymorphic and is either a disassociated pointer or 15387bd9461SValentin Clement // unallocated allocatable, the result is false. 15487bd9461SValentin Clement // Otherwise if the dynamic type of A or MOLD is extensible, the result is 15587bd9461SValentin Clement // true if and only if the dynamic type of A is an extension type of the 15687bd9461SValentin Clement // dynamic type of MOLD. 157dffd93b3SPeter Klausler for (const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)}; 158dffd93b3SPeter Klausler derivedTypeA; derivedTypeA = derivedTypeA->GetParentType()) { 15987bd9461SValentin Clement if (CompareDerivedType(derivedTypeA, derivedTypeMold)) { 16087bd9461SValentin Clement return true; 16187bd9461SValentin Clement } 16287bd9461SValentin Clement } 16387bd9461SValentin Clement return false; 164dffd93b3SPeter Klausler } else { 165dffd93b3SPeter Klausler // MOLD is unlimited polymorphic and unallocated/disassociated. 166dffd93b3SPeter Klausler return true; 167dffd93b3SPeter Klausler } 16887bd9461SValentin Clement } 16987bd9461SValentin Clement 170b4b23ff7SSlava Zakharin void RTDEF(DestroyWithoutFinalization)(const Descriptor &descriptor) { 171da60b9e7SSlava Zakharin if (const DescriptorAddendum * addendum{descriptor.Addendum()}) { 172da60b9e7SSlava Zakharin if (const auto *derived{addendum->derivedType()}) { 173da60b9e7SSlava Zakharin if (!derived->noDestructionNeeded()) { 174b21c24c3SPeter Klausler Destroy(descriptor, /*finalize=*/false, *derived, nullptr); 175da60b9e7SSlava Zakharin } 176da60b9e7SSlava Zakharin } 177da60b9e7SSlava Zakharin } 178da60b9e7SSlava Zakharin } 179da60b9e7SSlava Zakharin 18076facde3SSlava Zakharin RT_EXT_API_GROUP_END 181a48e4168Speter klausler } // extern "C" 182a48e4168Speter klausler } // namespace Fortran::runtime 183