|  | //===- InternalNamesTest.cpp -- InternalNames unit tests ------------------===// | 
|  | // | 
|  | // 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "flang/Optimizer/Support/InternalNames.h" | 
|  | #include "gtest/gtest.h" | 
|  | #include <optional> | 
|  | #include <string> | 
|  |  | 
|  | using namespace fir; | 
|  | using llvm::SmallVector; | 
|  |  | 
|  | struct DeconstructedName { | 
|  | DeconstructedName(llvm::StringRef name) : name{name} {} | 
|  | DeconstructedName(llvm::ArrayRef<std::string> modules, | 
|  | llvm::ArrayRef<std::string> procs, std::int64_t blockId, | 
|  | llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds) | 
|  | : modules{modules}, procs{procs}, blockId{blockId}, name{name}, | 
|  | kinds{kinds} {} | 
|  |  | 
|  | bool isObjEqual(const NameUniquer::DeconstructedName &actualObj) { | 
|  | return actualObj.modules == modules && actualObj.procs == procs && | 
|  | actualObj.blockId == blockId && actualObj.name == name && | 
|  | actualObj.kinds == kinds; | 
|  | } | 
|  |  | 
|  | llvm::SmallVector<std::string> modules; | 
|  | llvm::SmallVector<std::string> procs; | 
|  | std::int64_t blockId; | 
|  | std::string name; | 
|  | llvm::SmallVector<std::int64_t> kinds; | 
|  | }; | 
|  |  | 
|  | void validateDeconstructedName( | 
|  | std::pair<NameUniquer::NameKind, NameUniquer::DeconstructedName> &actual, | 
|  | NameUniquer::NameKind &expectedNameKind, | 
|  | struct DeconstructedName &components) { | 
|  | EXPECT_EQ(actual.first, expectedNameKind) | 
|  | << "Possible error: NameKind mismatch"; | 
|  | ASSERT_TRUE(components.isObjEqual(actual.second)) | 
|  | << "Possible error: DeconstructedName mismatch"; | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doCommonBlockTest) { | 
|  | std::string actual = NameUniquer::doCommonBlock("hello"); | 
|  | std::string actualBlank = NameUniquer::doCommonBlock(""); | 
|  | std::string expectedMangledName = "_QChello"; | 
|  | std::string expectedMangledNameBlank = "_QC"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | ASSERT_EQ(actualBlank, expectedMangledNameBlank); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doGeneratedTest) { | 
|  | std::string actual = NameUniquer::doGenerated("@MAIN"); | 
|  | std::string expectedMangledName = "_QQ@MAIN"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | std::string actual1 = NameUniquer::doGenerated("@_ZNSt8ios_base4InitC1Ev"); | 
|  | std::string expectedMangledName1 = "_QQ@_ZNSt8ios_base4InitC1Ev"; | 
|  | ASSERT_EQ(actual1, expectedMangledName1); | 
|  |  | 
|  | std::string actual2 = NameUniquer::doGenerated("_QQ@MAIN"); | 
|  | std::string expectedMangledName2 = "_QQ_QQ@MAIN"; | 
|  | ASSERT_EQ(actual2, expectedMangledName2); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doConstantTest) { | 
|  | std::string actual = | 
|  | NameUniquer::doConstant({"mod1", "mod2"}, {"foo"}, 0, "Hello"); | 
|  | std::string expectedMangledName = "_QMmod1Smod2FfooEChello"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doProcedureTest) { | 
|  | std::string actual = NameUniquer::doProcedure({"mod1", "mod2"}, {}, "HeLLo"); | 
|  | std::string expectedMangledName = "_QMmod1Smod2Phello"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doTypeTest) { | 
|  | std::string actual = NameUniquer::doType({}, {}, 0, "mytype", {4, -1}); | 
|  | std::string expectedMangledName = "_QTmytypeK4KN1"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doIntrinsicTypeDescriptorTest) { | 
|  | using IntrinsicType = fir::NameUniquer::IntrinsicType; | 
|  | std::string actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::REAL, 42); | 
|  | std::string expectedMangledName = "_QYIrealK42"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::REAL, {}); | 
|  | expectedMangledName = "_QYIrealK0"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::INTEGER, 3); | 
|  | expectedMangledName = "_QYIintegerK3"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::LOGICAL, 2); | 
|  | expectedMangledName = "_QYIlogicalK2"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::CHARACTER, 4); | 
|  | expectedMangledName = "_QYIcharacterK4"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | actual = NameUniquer::doIntrinsicTypeDescriptor( | 
|  | {}, {}, 0, IntrinsicType::COMPLEX, 4); | 
|  | expectedMangledName = "_QYIcomplexK4"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doDispatchTableTest) { | 
|  | std::string actual = | 
|  | NameUniquer::doDispatchTable({}, {}, 0, "MyTYPE", {2, 8, 18}); | 
|  | std::string expectedMangledName = "_QDTmytypeK2K8K18"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doVariableTest) { | 
|  | std::string actual = NameUniquer::doVariable( | 
|  | {"mod1", "mod2"}, {""}, 0, "intvar"); // Function is present and is blank. | 
|  | std::string expectedMangledName = "_QMmod1Smod2FEintvar"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  |  | 
|  | std::string actual2 = NameUniquer::doVariable( | 
|  | {"mod1", "mod2"}, {}, 0, "intVariable"); // Function is not present. | 
|  | std::string expectedMangledName2 = "_QMmod1Smod2Eintvariable"; | 
|  | ASSERT_EQ(actual2, expectedMangledName2); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doProgramEntry) { | 
|  | llvm::StringRef actual = NameUniquer::doProgramEntry(); | 
|  | std::string expectedMangledName = "_QQmain"; | 
|  | ASSERT_EQ(actual.str(), expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, doNamelistGroup) { | 
|  | std::string actual = NameUniquer::doNamelistGroup({"mod1"}, {}, "nlg"); | 
|  | std::string expectedMangledName = "_QMmod1Nnlg"; | 
|  | ASSERT_EQ(actual, expectedMangledName); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, deconstructTest) { | 
|  | std::pair actual = NameUniquer::deconstruct("_QChello"); | 
|  | auto expectedNameKind = NameUniquer::NameKind::COMMON; | 
|  | struct DeconstructedName expectedComponents { | 
|  | {}, {}, 0, "hello", {} | 
|  | }; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, complexdeconstructTest) { | 
|  | using NameKind = fir::NameUniquer::NameKind; | 
|  | std::pair actual = NameUniquer::deconstruct("_QMmodSs1modSs2modFsubPfun"); | 
|  | auto expectedNameKind = NameKind::PROCEDURE; | 
|  | struct DeconstructedName expectedComponents = { | 
|  | {"mod", "s1mod", "s2mod"}, {"sub"}, 0, "fun", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QPsub"); | 
|  | expectedNameKind = NameKind::PROCEDURE; | 
|  | expectedComponents = {{}, {}, 0, "sub", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QCvariables"); | 
|  | expectedNameKind = NameKind::COMMON; | 
|  | expectedComponents = {{}, {}, 0, "variables", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QMmodEintvar"); | 
|  | expectedNameKind = NameKind::VARIABLE; | 
|  | expectedComponents = {{"mod"}, {}, 0, "intvar", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QMmodECpi"); | 
|  | expectedNameKind = NameKind::CONSTANT; | 
|  | expectedComponents = {{"mod"}, {}, 0, "pi", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QTyourtypeK4KN6"); | 
|  | expectedNameKind = NameKind::DERIVED_TYPE; | 
|  | expectedComponents = {{}, {}, 0, "yourtype", {4, -6}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QDTt"); | 
|  | expectedNameKind = NameKind::DISPATCH_TABLE; | 
|  | expectedComponents = {{}, {}, 0, "t", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  |  | 
|  | actual = NameUniquer::deconstruct("_QFmstartNmpitop"); | 
|  | expectedNameKind = NameKind::NAMELIST_GROUP; | 
|  | expectedComponents = {{}, {"mstart"}, 0, "mpitop", {}}; | 
|  | validateDeconstructedName(actual, expectedNameKind, expectedComponents); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, needExternalNameMangling) { | 
|  | ASSERT_FALSE( | 
|  | NameUniquer::needExternalNameMangling("_QMmodSs1modSs2modFsubPfun")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("omp_num_thread")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QDTmytypeK2K8K18")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("exit_")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QFfooEx")); | 
|  | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QFmstartNmpitop")); | 
|  | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QPfoo")); | 
|  | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QPbar")); | 
|  | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QCa")); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, isExternalFacingUniquedName) { | 
|  | std::pair result = NameUniquer::deconstruct("_QMmodSs1modSs2modFsubPfun"); | 
|  |  | 
|  | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("omp_num_thread"); | 
|  | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct(""); | 
|  | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("_QDTmytypeK2K8K18"); | 
|  | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("exit_"); | 
|  | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("_QPfoo"); | 
|  | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("_QPbar"); | 
|  | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | result = NameUniquer::deconstruct("_QCa"); | 
|  | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, getTypeDescriptorName) { | 
|  | std::string derivedTypeName = "_QMdispatch1Tp1"; | 
|  | std::string expectedBindingTableName = "_QMdispatch1E.dt.p1"; | 
|  | ASSERT_EQ(expectedBindingTableName, | 
|  | fir::NameUniquer::getTypeDescriptorName(derivedTypeName)); | 
|  | ASSERT_EQ("", fir::NameUniquer::getTypeDescriptorName("_QMdispatch1Pp1")); | 
|  | } | 
|  |  | 
|  | TEST(InternalNamesTest, getTypeDescriptorBindingTableName) { | 
|  | std::string derivedTypeName = "_QMdispatch1Tp1"; | 
|  | std::string expectedBindingTableName = "_QMdispatch1E.v.p1"; | 
|  | ASSERT_EQ(expectedBindingTableName, | 
|  | fir::NameUniquer::getTypeDescriptorBindingTableName(derivedTypeName)); | 
|  | ASSERT_EQ("", | 
|  | fir::NameUniquer::getTypeDescriptorBindingTableName("_QMdispatch1Pp1")); | 
|  | } | 
|  |  | 
|  | // main() from gtest_main |