| 1 | //===- InternalNamesTest.cpp -- InternalNames unit tests ------------------===// |
| 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 | #include "flang/Optimizer/Support/InternalNames.h" |
| 10 | #include "gtest/gtest.h" |
| 11 | #include <optional> |
| 12 | #include <string> |
| 13 | |
| 14 | using namespace fir; |
| 15 | using llvm::SmallVector; |
| 16 | |
| 17 | struct DeconstructedName { |
| 18 | DeconstructedName(llvm::StringRef name) : name{name} {} |
| 19 | DeconstructedName(llvm::ArrayRef<std::string> modules, |
| 20 | llvm::ArrayRef<std::string> procs, std::int64_t blockId, |
| 21 | llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds) |
| 22 | : modules{modules}, procs{procs}, blockId{blockId}, name{name}, |
| 23 | kinds{kinds} {} |
| 24 | |
| 25 | bool isObjEqual(const NameUniquer::DeconstructedName &actualObj) { |
| 26 | return actualObj.modules == modules && actualObj.procs == procs && |
| 27 | actualObj.blockId == blockId && actualObj.name == name && |
| 28 | actualObj.kinds == kinds; |
| 29 | } |
| 30 | |
| 31 | llvm::SmallVector<std::string> modules; |
| 32 | llvm::SmallVector<std::string> procs; |
| 33 | std::int64_t blockId; |
| 34 | std::string name; |
| 35 | llvm::SmallVector<std::int64_t> kinds; |
| 36 | }; |
| 37 | |
| 38 | void validateDeconstructedName( |
| 39 | std::pair<NameUniquer::NameKind, NameUniquer::DeconstructedName> &actual, |
| 40 | NameUniquer::NameKind &expectedNameKind, |
| 41 | struct DeconstructedName &components) { |
| 42 | EXPECT_EQ(actual.first, expectedNameKind) |
| 43 | << "Possible error: NameKind mismatch" ; |
| 44 | ASSERT_TRUE(components.isObjEqual(actual.second)) |
| 45 | << "Possible error: DeconstructedName mismatch" ; |
| 46 | } |
| 47 | |
| 48 | TEST(InternalNamesTest, doCommonBlockTest) { |
| 49 | std::string actual = NameUniquer::doCommonBlock("hello" ); |
| 50 | std::string actualBlank = NameUniquer::doCommonBlock("" ); |
| 51 | std::string expectedMangledName = "_QChello" ; |
| 52 | std::string expectedMangledNameBlank = "_QC" ; |
| 53 | ASSERT_EQ(actual, expectedMangledName); |
| 54 | ASSERT_EQ(actualBlank, expectedMangledNameBlank); |
| 55 | } |
| 56 | |
| 57 | TEST(InternalNamesTest, doGeneratedTest) { |
| 58 | std::string actual = NameUniquer::doGenerated("@MAIN" ); |
| 59 | std::string expectedMangledName = "_QQ@MAIN" ; |
| 60 | ASSERT_EQ(actual, expectedMangledName); |
| 61 | |
| 62 | std::string actual1 = NameUniquer::doGenerated("@_ZNSt8ios_base4InitC1Ev" ); |
| 63 | std::string expectedMangledName1 = "_QQ@_ZNSt8ios_base4InitC1Ev" ; |
| 64 | ASSERT_EQ(actual1, expectedMangledName1); |
| 65 | |
| 66 | std::string actual2 = NameUniquer::doGenerated("_QQ@MAIN" ); |
| 67 | std::string expectedMangledName2 = "_QQ_QQ@MAIN" ; |
| 68 | ASSERT_EQ(actual2, expectedMangledName2); |
| 69 | } |
| 70 | |
| 71 | TEST(InternalNamesTest, doConstantTest) { |
| 72 | std::string actual = |
| 73 | NameUniquer::doConstant({"mod1" , "mod2" }, {"foo" }, 0, "Hello" ); |
| 74 | std::string expectedMangledName = "_QMmod1Smod2FfooEChello" ; |
| 75 | ASSERT_EQ(actual, expectedMangledName); |
| 76 | } |
| 77 | |
| 78 | TEST(InternalNamesTest, doProcedureTest) { |
| 79 | std::string actual = NameUniquer::doProcedure({"mod1" , "mod2" }, {}, "HeLLo" ); |
| 80 | std::string expectedMangledName = "_QMmod1Smod2Phello" ; |
| 81 | ASSERT_EQ(actual, expectedMangledName); |
| 82 | } |
| 83 | |
| 84 | TEST(InternalNamesTest, doTypeTest) { |
| 85 | std::string actual = NameUniquer::doType({}, {}, 0, "mytype" , {4, -1}); |
| 86 | std::string expectedMangledName = "_QTmytypeK4KN1" ; |
| 87 | ASSERT_EQ(actual, expectedMangledName); |
| 88 | } |
| 89 | |
| 90 | TEST(InternalNamesTest, doIntrinsicTypeDescriptorTest) { |
| 91 | using IntrinsicType = fir::NameUniquer::IntrinsicType; |
| 92 | std::string actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 93 | {}, {}, 0, IntrinsicType::REAL, 42); |
| 94 | std::string expectedMangledName = "_QYIrealK42" ; |
| 95 | ASSERT_EQ(actual, expectedMangledName); |
| 96 | |
| 97 | actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 98 | {}, {}, 0, IntrinsicType::REAL, {}); |
| 99 | expectedMangledName = "_QYIrealK0" ; |
| 100 | ASSERT_EQ(actual, expectedMangledName); |
| 101 | |
| 102 | actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 103 | {}, {}, 0, IntrinsicType::INTEGER, 3); |
| 104 | expectedMangledName = "_QYIintegerK3" ; |
| 105 | ASSERT_EQ(actual, expectedMangledName); |
| 106 | |
| 107 | actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 108 | {}, {}, 0, IntrinsicType::LOGICAL, 2); |
| 109 | expectedMangledName = "_QYIlogicalK2" ; |
| 110 | ASSERT_EQ(actual, expectedMangledName); |
| 111 | |
| 112 | actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 113 | {}, {}, 0, IntrinsicType::CHARACTER, 4); |
| 114 | expectedMangledName = "_QYIcharacterK4" ; |
| 115 | ASSERT_EQ(actual, expectedMangledName); |
| 116 | |
| 117 | actual = NameUniquer::doIntrinsicTypeDescriptor( |
| 118 | {}, {}, 0, IntrinsicType::COMPLEX, 4); |
| 119 | expectedMangledName = "_QYIcomplexK4" ; |
| 120 | ASSERT_EQ(actual, expectedMangledName); |
| 121 | } |
| 122 | |
| 123 | TEST(InternalNamesTest, doDispatchTableTest) { |
| 124 | std::string actual = |
| 125 | NameUniquer::doDispatchTable({}, {}, 0, "MyTYPE" , {2, 8, 18}); |
| 126 | std::string expectedMangledName = "_QDTmytypeK2K8K18" ; |
| 127 | ASSERT_EQ(actual, expectedMangledName); |
| 128 | } |
| 129 | |
| 130 | TEST(InternalNamesTest, doVariableTest) { |
| 131 | std::string actual = NameUniquer::doVariable( |
| 132 | {"mod1" , "mod2" }, {"" }, 0, "intvar" ); // Function is present and is blank. |
| 133 | std::string expectedMangledName = "_QMmod1Smod2FEintvar" ; |
| 134 | ASSERT_EQ(actual, expectedMangledName); |
| 135 | |
| 136 | std::string actual2 = NameUniquer::doVariable( |
| 137 | {"mod1" , "mod2" }, {}, 0, "intVariable" ); // Function is not present. |
| 138 | std::string expectedMangledName2 = "_QMmod1Smod2Eintvariable" ; |
| 139 | ASSERT_EQ(actual2, expectedMangledName2); |
| 140 | } |
| 141 | |
| 142 | TEST(InternalNamesTest, doProgramEntry) { |
| 143 | llvm::StringRef actual = NameUniquer::doProgramEntry(); |
| 144 | std::string expectedMangledName = "_QQmain" ; |
| 145 | ASSERT_EQ(actual.str(), expectedMangledName); |
| 146 | } |
| 147 | |
| 148 | TEST(InternalNamesTest, doNamelistGroup) { |
| 149 | std::string actual = NameUniquer::doNamelistGroup({"mod1" }, {}, "nlg" ); |
| 150 | std::string expectedMangledName = "_QMmod1Nnlg" ; |
| 151 | ASSERT_EQ(actual, expectedMangledName); |
| 152 | } |
| 153 | |
| 154 | TEST(InternalNamesTest, deconstructTest) { |
| 155 | std::pair actual = NameUniquer::deconstruct("_QChello" ); |
| 156 | auto expectedNameKind = NameUniquer::NameKind::COMMON; |
| 157 | struct DeconstructedName expectedComponents { |
| 158 | {}, {}, 0, "hello" , {} |
| 159 | }; |
| 160 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 161 | } |
| 162 | |
| 163 | TEST(InternalNamesTest, complexdeconstructTest) { |
| 164 | using NameKind = fir::NameUniquer::NameKind; |
| 165 | std::pair actual = NameUniquer::deconstruct("_QMmodSs1modSs2modFsubPfun" ); |
| 166 | auto expectedNameKind = NameKind::PROCEDURE; |
| 167 | struct DeconstructedName expectedComponents = { |
| 168 | {"mod" , "s1mod" , "s2mod" }, {"sub" }, 0, "fun" , {}}; |
| 169 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 170 | |
| 171 | actual = NameUniquer::deconstruct("_QPsub" ); |
| 172 | expectedNameKind = NameKind::PROCEDURE; |
| 173 | expectedComponents = {{}, {}, 0, "sub" , {}}; |
| 174 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 175 | |
| 176 | actual = NameUniquer::deconstruct("_QCvariables" ); |
| 177 | expectedNameKind = NameKind::COMMON; |
| 178 | expectedComponents = {{}, {}, 0, "variables" , {}}; |
| 179 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 180 | |
| 181 | actual = NameUniquer::deconstruct("_QMmodEintvar" ); |
| 182 | expectedNameKind = NameKind::VARIABLE; |
| 183 | expectedComponents = {{"mod" }, {}, 0, "intvar" , {}}; |
| 184 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 185 | |
| 186 | actual = NameUniquer::deconstruct("_QMmodECpi" ); |
| 187 | expectedNameKind = NameKind::CONSTANT; |
| 188 | expectedComponents = {{"mod" }, {}, 0, "pi" , {}}; |
| 189 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 190 | |
| 191 | actual = NameUniquer::deconstruct("_QTyourtypeK4KN6" ); |
| 192 | expectedNameKind = NameKind::DERIVED_TYPE; |
| 193 | expectedComponents = {{}, {}, 0, "yourtype" , {4, -6}}; |
| 194 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 195 | |
| 196 | actual = NameUniquer::deconstruct("_QDTt" ); |
| 197 | expectedNameKind = NameKind::DISPATCH_TABLE; |
| 198 | expectedComponents = {{}, {}, 0, "t" , {}}; |
| 199 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 200 | |
| 201 | actual = NameUniquer::deconstruct("_QFmstartNmpitop" ); |
| 202 | expectedNameKind = NameKind::NAMELIST_GROUP; |
| 203 | expectedComponents = {{}, {"mstart" }, 0, "mpitop" , {}}; |
| 204 | validateDeconstructedName(actual, expectedNameKind, expectedComponents); |
| 205 | } |
| 206 | |
| 207 | TEST(InternalNamesTest, needExternalNameMangling) { |
| 208 | ASSERT_FALSE( |
| 209 | NameUniquer::needExternalNameMangling("_QMmodSs1modSs2modFsubPfun" )); |
| 210 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("omp_num_thread" )); |
| 211 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("" )); |
| 212 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QDTmytypeK2K8K18" )); |
| 213 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("exit_" )); |
| 214 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QFfooEx" )); |
| 215 | ASSERT_FALSE(NameUniquer::needExternalNameMangling("_QFmstartNmpitop" )); |
| 216 | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QPfoo" )); |
| 217 | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QPbar" )); |
| 218 | ASSERT_TRUE(NameUniquer::needExternalNameMangling("_QCa" )); |
| 219 | } |
| 220 | |
| 221 | TEST(InternalNamesTest, isExternalFacingUniquedName) { |
| 222 | std::pair result = NameUniquer::deconstruct("_QMmodSs1modSs2modFsubPfun" ); |
| 223 | |
| 224 | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); |
| 225 | result = NameUniquer::deconstruct("omp_num_thread" ); |
| 226 | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); |
| 227 | result = NameUniquer::deconstruct("" ); |
| 228 | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); |
| 229 | result = NameUniquer::deconstruct("_QDTmytypeK2K8K18" ); |
| 230 | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); |
| 231 | result = NameUniquer::deconstruct("exit_" ); |
| 232 | ASSERT_FALSE(NameUniquer::isExternalFacingUniquedName(result)); |
| 233 | result = NameUniquer::deconstruct("_QPfoo" ); |
| 234 | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); |
| 235 | result = NameUniquer::deconstruct("_QPbar" ); |
| 236 | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); |
| 237 | result = NameUniquer::deconstruct("_QCa" ); |
| 238 | ASSERT_TRUE(NameUniquer::isExternalFacingUniquedName(result)); |
| 239 | } |
| 240 | |
| 241 | TEST(InternalNamesTest, getTypeDescriptorName) { |
| 242 | std::string derivedTypeName = "_QMdispatch1Tp1" ; |
| 243 | std::string expectedBindingTableName = "_QMdispatch1E.dt.p1" ; |
| 244 | ASSERT_EQ(expectedBindingTableName, |
| 245 | fir::NameUniquer::getTypeDescriptorName(derivedTypeName)); |
| 246 | ASSERT_EQ("" , fir::NameUniquer::getTypeDescriptorName("_QMdispatch1Pp1" )); |
| 247 | } |
| 248 | |
| 249 | TEST(InternalNamesTest, getTypeDescriptorBindingTableName) { |
| 250 | std::string derivedTypeName = "_QMdispatch1Tp1" ; |
| 251 | std::string expectedBindingTableName = "_QMdispatch1E.v.p1" ; |
| 252 | ASSERT_EQ(expectedBindingTableName, |
| 253 | fir::NameUniquer::getTypeDescriptorBindingTableName(derivedTypeName)); |
| 254 | ASSERT_EQ("" , |
| 255 | fir::NameUniquer::getTypeDescriptorBindingTableName("_QMdispatch1Pp1" )); |
| 256 | } |
| 257 | |
| 258 | // main() from gtest_main |
| 259 | |