================
@@ -4230,6 +4230,98 @@ static bool
CheckCompatibleDistinctUltimates(SemanticsContext &context,
return true; // don't try to merge generics (or whatever)
}
+static bool AreSameProcedureForUseAssociation(
+ SemanticsContext &context, const Symbol &p1, const Symbol &p2) {
+ const Symbol &ultimate1{p1.GetUltimate()};
+ const Symbol &ultimate2{p2.GetUltimate()};
+ if (&ultimate1 == &ultimate2) {
+ return true;
+ } else if (ultimate1.name() != ultimate2.name()) {
+ return false;
+ } else if (ultimate1.attrs().test(Attr::INTRINSIC) ||
+ ultimate2.attrs().test(Attr::INTRINSIC)) {
+ return ultimate1.attrs().test(Attr::INTRINSIC) &&
+ ultimate2.attrs().test(Attr::INTRINSIC);
+ }
+ if (!IsProcedure(ultimate1) || IsPointer(ultimate1) ||
+ !IsProcedure(ultimate2) || IsPointer(ultimate2) ||
+ ClassifyProcedure(ultimate1) != ClassifyProcedure(ultimate2)) {
+ return false;
+ }
+ auto classification{ClassifyProcedure(ultimate1)};
+ if (classification == ProcedureDefinitionClass::Module) {
+ return AreSameModuleSymbol(ultimate1, ultimate2);
+ }
+ if (classification != ProcedureDefinitionClass::External) {
+ return false;
+ }
+ const auto *subp1{ultimate1.detailsIf<SubprogramDetails>()};
+ const auto *subp2{ultimate2.detailsIf<SubprogramDetails>()};
+ if (!subp1 || !subp1->isInterface() || !subp2 || !subp2->isInterface()) {
+ return false;
+ }
+ auto chars1{evaluate::characteristics::Procedure::Characterize(
+ ultimate1, context.foldingContext())};
+ auto chars2{evaluate::characteristics::Procedure::Characterize(
+ ultimate2, context.foldingContext())};
+ return chars1 && chars2 && *chars1 == *chars2;
+}
+
+static bool HasCUDADummyDataAttribute(const Symbol &procedure) {
+ if (const auto *subp{
+ procedure.GetUltimate().detailsIf<SubprogramDetails>()}) {
+ for (const Symbol *dummy : subp->dummyArgs()) {
+ if (dummy && GetCUDADataAttr(dummy)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+struct IntrinsicModuleUseAssociationRule {
+ const char *moduleName;
+ const char *genericName;
+ bool (*matches)(SemanticsContext &, const GenericDetails &, const Symbol &);
+};
+
+static bool MatchesCublasZgemm(SemanticsContext &context,
+ const GenericDetails &generic, const Symbol &other) {
+ const Symbol *specific{generic.specific()};
+ if (!specific ||
+ !AreSameProcedureForUseAssociation(context, *specific, other)) {
+ return false;
+ }
+ bool containsSpecific{false};
+ bool hasCUDAOverload{false};
+ for (const Symbol &candidate : generic.specificProcs()) {
+ containsSpecific |= &candidate.GetUltimate() == &specific->GetUltimate();
+ hasCUDAOverload |= HasCUDADummyDataAttribute(candidate);
+ }
+ return containsSpecific && hasCUDAOverload;
+}
+
+static const IntrinsicModuleUseAssociationRule *
+FindIntrinsicModuleUseAssociationRule(
+ SemanticsContext &context, const Symbol &generic, const Symbol &other) {
----------------
mleair wrote:
I suggest adding a comment here for the table below that explains its purpose
and lets the developer know that it can be used in the future for adding more
intrinsic module generic entries that should take precedence over an equivalent
external interface during USE association. Maybe that comment can be:
https://github.com/llvm/llvm-project/pull/217455
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits