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