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