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 | |