1 | //===----- unittests/CSKYAttributeParserTest.cpp --------------------------===// |
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 | #include "llvm/Support/CSKYAttributeParser.h" |
9 | #include "llvm/Support/ARMBuildAttributes.h" |
10 | #include "llvm/Support/ELFAttributes.h" |
11 | #include "gtest/gtest.h" |
12 | #include <string> |
13 | |
14 | using namespace llvm; |
15 | |
16 | struct CSKYAttributeSection { |
17 | unsigned Tag; |
18 | struct { |
19 | unsigned IntValue; |
20 | const char *StringValue; |
21 | } Value; |
22 | |
23 | CSKYAttributeSection(unsigned tag, unsigned value) : Tag(tag) { |
24 | Value.IntValue = value; |
25 | } |
26 | |
27 | CSKYAttributeSection(unsigned tag, const char *value) : Tag(tag) { |
28 | Value.StringValue = value; |
29 | } |
30 | |
31 | void writeInt(raw_ostream &OS) { |
32 | OS.flush(); |
33 | // Format version. |
34 | OS << 'A' |
35 | // uint32_t = VendorHeaderSize + TagHeaderSize + ContentsSize. |
36 | << (uint8_t)16 << (uint8_t)0 << (uint8_t)0 |
37 | << (uint8_t)0 |
38 | // CurrentVendor. |
39 | << "csky" |
40 | << '\0' |
41 | // ELFAttrs::File. |
42 | << (uint8_t)1 |
43 | // uint32_t = TagHeaderSize + ContentsSize. |
44 | << (uint8_t)6 << (uint8_t)0 << (uint8_t)0 |
45 | << (uint8_t)0 |
46 | // Tag |
47 | << (uint8_t)Tag |
48 | // IntValue |
49 | << (uint8_t)Value.IntValue; |
50 | } |
51 | |
52 | void writeString(raw_ostream &OS) { |
53 | OS.flush(); |
54 | // Format version. |
55 | OS << 'A' |
56 | // uint32_t = VendorHeaderSize + TagHeaderSize + ContentsSize. |
57 | << (uint8_t)(16 + strlen(s: Value.StringValue)) << (uint8_t)0 << (uint8_t)0 |
58 | << (uint8_t)0 |
59 | // CurrentVendor. |
60 | << "csky" |
61 | << '\0' |
62 | // ELFAttrs::File. |
63 | << (uint8_t)1 |
64 | // uint32_t = TagHeaderSize + ContentsSize. |
65 | << (uint8_t)(6 + strlen(s: Value.StringValue)) << (uint8_t)0 << (uint8_t)0 |
66 | << (uint8_t)0 |
67 | // Tag |
68 | << (uint8_t)Tag |
69 | // StringValue |
70 | << Value.StringValue << '\0'; |
71 | } |
72 | }; |
73 | |
74 | static bool testAttributeInt(unsigned Tag, unsigned Value, unsigned ExpectedTag, |
75 | unsigned ExpectedValue) { |
76 | std::string buffer; |
77 | raw_string_ostream OS(buffer); |
78 | CSKYAttributeSection Section(Tag, Value); |
79 | Section.writeInt(OS); |
80 | ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(OS.str().c_str()), |
81 | OS.str().size()); |
82 | |
83 | CSKYAttributeParser Parser; |
84 | cantFail(Err: Parser.parse(section: Bytes, endian: llvm::endianness::little)); |
85 | |
86 | std::optional<unsigned> Attr = Parser.getAttributeValue(tag: ExpectedTag); |
87 | return Attr && *Attr == ExpectedValue; |
88 | } |
89 | |
90 | static bool testAttributeString(unsigned Tag, const char *Value, |
91 | unsigned ExpectedTag, |
92 | const char *ExpectedValue) { |
93 | std::string buffer; |
94 | raw_string_ostream OS(buffer); |
95 | CSKYAttributeSection Section(Tag, Value); |
96 | Section.writeString(OS); |
97 | ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(OS.str().c_str()), |
98 | OS.str().size()); |
99 | |
100 | CSKYAttributeParser Parser; |
101 | cantFail(Err: Parser.parse(section: Bytes, endian: llvm::endianness::little)); |
102 | |
103 | std::optional<StringRef> Attr = Parser.getAttributeString(tag: ExpectedTag); |
104 | return Attr && *Attr == ExpectedValue; |
105 | } |
106 | |
107 | static void testParseError(unsigned Tag, unsigned Value, const char *msg) { |
108 | std::string buffer; |
109 | raw_string_ostream OS(buffer); |
110 | CSKYAttributeSection Section(Tag, Value); |
111 | Section.writeInt(OS); |
112 | ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(OS.str().c_str()), |
113 | OS.str().size()); |
114 | |
115 | CSKYAttributeParser Parser; |
116 | Error e = Parser.parse(section: Bytes, endian: llvm::endianness::little); |
117 | EXPECT_STREQ(toString(std::move(e)).c_str(), msg); |
118 | } |
119 | |
120 | static bool testTagString(unsigned Tag, const char *name) { |
121 | return ELFAttrs::attrTypeAsString(attr: Tag, tagNameMap: CSKYAttrs::getCSKYAttributeTags()) |
122 | .str() == name; |
123 | } |
124 | |
125 | TEST(ArchName, testAttribute) { |
126 | EXPECT_TRUE(testTagString(4, "Tag_CSKY_ARCH_NAME" )); |
127 | EXPECT_TRUE( |
128 | testAttributeString(4, "ck860" , CSKYAttrs::CSKY_ARCH_NAME, "ck860" )); |
129 | EXPECT_FALSE( |
130 | testAttributeString(4, "ck86" , CSKYAttrs::CSKY_ARCH_NAME, "ck60" )); |
131 | } |
132 | |
133 | TEST(CPUName, testAttribute) { |
134 | EXPECT_TRUE(testTagString(5, "Tag_CSKY_CPU_NAME" )); |
135 | EXPECT_TRUE( |
136 | testAttributeString(5, "ck860fv" , CSKYAttrs::CSKY_CPU_NAME, "ck860fv" )); |
137 | EXPECT_FALSE( |
138 | testAttributeString(5, "ck860" , CSKYAttrs::CSKY_CPU_NAME, "ck860fv" )); |
139 | } |
140 | |
141 | TEST(DSPVersion, testAttribute) { |
142 | EXPECT_TRUE(testTagString(8, "Tag_CSKY_DSP_VERSION" )); |
143 | EXPECT_TRUE(testAttributeInt(8, 1, CSKYAttrs::CSKY_DSP_VERSION, |
144 | CSKYAttrs::DSP_VERSION_EXTENSION)); |
145 | EXPECT_TRUE(testAttributeInt(8, 2, CSKYAttrs::CSKY_DSP_VERSION, |
146 | CSKYAttrs::DSP_VERSION_2)); |
147 | EXPECT_FALSE(testAttributeInt(8, 0, CSKYAttrs::CSKY_DSP_VERSION, |
148 | CSKYAttrs::DSP_VERSION_EXTENSION)); |
149 | testParseError(Tag: 8, Value: 3, msg: "unknown Tag_CSKY_DSP_VERSION value: 3" ); |
150 | } |
151 | |
152 | TEST(VDSPVersion, testAttribute) { |
153 | EXPECT_TRUE(testTagString(9, "Tag_CSKY_VDSP_VERSION" )); |
154 | EXPECT_TRUE(testAttributeInt(9, 1, CSKYAttrs::CSKY_VDSP_VERSION, |
155 | CSKYAttrs::VDSP_VERSION_1)); |
156 | EXPECT_TRUE(testAttributeInt(9, 2, CSKYAttrs::CSKY_VDSP_VERSION, |
157 | CSKYAttrs::VDSP_VERSION_2)); |
158 | EXPECT_FALSE(testAttributeInt(9, 0, CSKYAttrs::CSKY_VDSP_VERSION, |
159 | CSKYAttrs::VDSP_VERSION_2)); |
160 | testParseError(Tag: 9, Value: 3, msg: "unknown Tag_CSKY_VDSP_VERSION value: 3" ); |
161 | } |
162 | |
163 | TEST(FPUVersion, testAttribute) { |
164 | EXPECT_TRUE(testTagString(16, "Tag_CSKY_FPU_VERSION" )); |
165 | EXPECT_TRUE(testAttributeInt(16, 1, CSKYAttrs::CSKY_FPU_VERSION, |
166 | CSKYAttrs::FPU_VERSION_1)); |
167 | EXPECT_TRUE(testAttributeInt(16, 2, CSKYAttrs::CSKY_FPU_VERSION, |
168 | CSKYAttrs::FPU_VERSION_2)); |
169 | EXPECT_TRUE(testAttributeInt(16, 3, CSKYAttrs::CSKY_FPU_VERSION, |
170 | CSKYAttrs::FPU_VERSION_3)); |
171 | EXPECT_FALSE(testAttributeInt(16, 0, CSKYAttrs::CSKY_FPU_VERSION, |
172 | CSKYAttrs::FPU_VERSION_3)); |
173 | testParseError(Tag: 16, Value: 4, msg: "unknown Tag_CSKY_FPU_VERSION value: 4" ); |
174 | } |
175 | |
176 | TEST(FPUABI, testAttribute) { |
177 | EXPECT_TRUE(testTagString(17, "Tag_CSKY_FPU_ABI" )); |
178 | EXPECT_TRUE(testAttributeInt(17, 1, CSKYAttrs::CSKY_FPU_ABI, |
179 | CSKYAttrs::FPU_ABI_SOFT)); |
180 | EXPECT_TRUE(testAttributeInt(17, 2, CSKYAttrs::CSKY_FPU_ABI, |
181 | CSKYAttrs::FPU_ABI_SOFTFP)); |
182 | EXPECT_TRUE(testAttributeInt(17, 3, CSKYAttrs::CSKY_FPU_ABI, |
183 | CSKYAttrs::FPU_ABI_HARD)); |
184 | EXPECT_FALSE(testAttributeInt(17, 0, CSKYAttrs::CSKY_FPU_ABI, |
185 | CSKYAttrs::FPU_ABI_HARD)); |
186 | testParseError(Tag: 17, Value: 4, msg: "unknown Tag_CSKY_FPU_ABI value: 4" ); |
187 | } |
188 | |
189 | TEST(FPURounding, testAttribute) { |
190 | EXPECT_TRUE(testTagString(18, "Tag_CSKY_FPU_ROUNDING" )); |
191 | EXPECT_TRUE( |
192 | testAttributeInt(18, 0, CSKYAttrs::CSKY_FPU_ROUNDING, CSKYAttrs::NONE)); |
193 | EXPECT_TRUE( |
194 | testAttributeInt(18, 1, CSKYAttrs::CSKY_FPU_ROUNDING, CSKYAttrs::NEEDED)); |
195 | testParseError(Tag: 18, Value: 2, msg: "unknown Tag_CSKY_FPU_ROUNDING value: 2" ); |
196 | } |
197 | |
198 | TEST(FPUDenormal, testAttribute) { |
199 | EXPECT_TRUE(testTagString(19, "Tag_CSKY_FPU_DENORMAL" )); |
200 | EXPECT_TRUE( |
201 | testAttributeInt(19, 0, CSKYAttrs::CSKY_FPU_DENORMAL, CSKYAttrs::NONE)); |
202 | EXPECT_TRUE( |
203 | testAttributeInt(19, 1, CSKYAttrs::CSKY_FPU_DENORMAL, CSKYAttrs::NEEDED)); |
204 | testParseError(Tag: 19, Value: 2, msg: "unknown Tag_CSKY_FPU_DENORMAL value: 2" ); |
205 | } |
206 | |
207 | TEST(FPUException, testAttribute) { |
208 | EXPECT_TRUE(testTagString(20, "Tag_CSKY_FPU_EXCEPTION" )); |
209 | EXPECT_TRUE( |
210 | testAttributeInt(20, 0, CSKYAttrs::CSKY_FPU_EXCEPTION, CSKYAttrs::NONE)); |
211 | EXPECT_TRUE(testAttributeInt(20, 1, CSKYAttrs::CSKY_FPU_EXCEPTION, |
212 | CSKYAttrs::NEEDED)); |
213 | testParseError(Tag: 20, Value: 2, msg: "unknown Tag_CSKY_FPU_EXCEPTION value: 2" ); |
214 | } |
215 | |
216 | TEST(FPUNumberModule, testAttribute) { |
217 | EXPECT_TRUE(testTagString(21, "Tag_CSKY_FPU_NUMBER_MODULE" )); |
218 | EXPECT_TRUE(testAttributeString( |
219 | 21, "IEEE 754" , CSKYAttrs::CSKY_FPU_NUMBER_MODULE, "IEEE 754" )); |
220 | EXPECT_FALSE(testAttributeString( |
221 | 21, "IEEE 755" , CSKYAttrs::CSKY_FPU_NUMBER_MODULE, "IEEE 754" )); |
222 | } |
223 | |
224 | TEST(FPUHardFP, testAttribute) { |
225 | EXPECT_TRUE(testTagString(22, "Tag_CSKY_FPU_HARDFP" )); |
226 | EXPECT_TRUE(testAttributeInt(22, 1, CSKYAttrs::CSKY_FPU_HARDFP, |
227 | CSKYAttrs::FPU_HARDFP_HALF)); |
228 | EXPECT_TRUE(testAttributeInt(22, 2, CSKYAttrs::CSKY_FPU_HARDFP, |
229 | CSKYAttrs::FPU_HARDFP_SINGLE)); |
230 | EXPECT_TRUE(testAttributeInt(22, 4, CSKYAttrs::CSKY_FPU_HARDFP, |
231 | CSKYAttrs::FPU_HARDFP_DOUBLE)); |
232 | EXPECT_FALSE(testAttributeInt(22, 3, CSKYAttrs::CSKY_FPU_HARDFP, |
233 | CSKYAttrs::FPU_HARDFP_DOUBLE)); |
234 | testParseError(Tag: 22, Value: 0, msg: "unknown Tag_CSKY_FPU_HARDFP value: 0" ); |
235 | testParseError(Tag: 22, Value: 8, msg: "unknown Tag_CSKY_FPU_HARDFP value: 8" ); |
236 | } |
237 | |