LLVM 20.0.0git
ARMAttributeParser.cpp
Go to the documentation of this file.
1//===- ARMAttributeParser.cpp - ARM Attribute Information Printer ---------===//
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
12#include "llvm/Support/Errc.h"
14#include <optional>
15
16using namespace llvm;
17using namespace llvm::ARMBuildAttrs;
18
19#define ATTRIBUTE_HANDLER(attr) \
20 { ARMBuildAttrs::attr, &ARMAttributeParser::attr }
21
22const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] =
23 {
24 {ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::stringAttribute},
25 {ARMBuildAttrs::CPU_name, &ARMAttributeParser::stringAttribute},
68};
69
70#undef ATTRIBUTE_HANDLER
71
72Error ARMAttributeParser::stringAttribute(AttrType tag) {
73 StringRef tagName =
74 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
76
77 if (sw) {
78 DictScope scope(*sw, "Attribute");
79 sw->printNumber("Tag", tag);
80 if (!tagName.empty())
81 sw->printString("TagName", tagName);
82 sw->printString("Value", desc);
83 }
84 return Error::success();
85}
86
87static const char *const CPU_arch_strings[] = {"Pre-v4",
88 "ARM v4",
89 "ARM v4T",
90 "ARM v5T",
91 "ARM v5TE",
92 "ARM v5TEJ",
93 "ARM v6",
94 "ARM v6KZ",
95 "ARM v6T2",
96 "ARM v6K",
97 "ARM v7",
98 "ARM v6-M",
99 "ARM v6S-M",
100 "ARM v7E-M",
101 "ARM v8-A",
102 "ARM v8-R",
103 "ARM v8-M Baseline",
104 "ARM v8-M Mainline",
105 nullptr,
106 nullptr,
107 nullptr,
108 "ARM v8.1-M Mainline",
109 "ARM v9-A"};
110
111Error ARMAttributeParser::CPU_arch(AttrType tag) {
112 return parseStringAttribute("CPU_arch", tag, ArrayRef(CPU_arch_strings));
113}
114
115Error ARMAttributeParser::CPU_arch_profile(AttrType tag) {
117
118 StringRef profile;
119 switch (value) {
120 default: profile = "Unknown"; break;
121 case 'A': profile = "Application"; break;
122 case 'R': profile = "Real-time"; break;
123 case 'M': profile = "Microcontroller"; break;
124 case 'S': profile = "Classic"; break;
125 case 0: profile = "None"; break;
126 }
127
128 printAttribute(tag, value, profile);
129 return Error::success();
130}
131
132Error ARMAttributeParser::ARM_ISA_use(AttrType tag) {
133 static const char *const strings[] = {"Not Permitted", "Permitted"};
134 return parseStringAttribute("ARM_ISA_use", tag, ArrayRef(strings));
135}
136
137Error ARMAttributeParser::THUMB_ISA_use(AttrType tag) {
138 static const char *const strings[] = {"Not Permitted", "Thumb-1", "Thumb-2",
139 "Permitted"};
140 return parseStringAttribute("THUMB_ISA_use", tag, ArrayRef(strings));
141}
142
143Error ARMAttributeParser::FP_arch(AttrType tag) {
144 static const char *const strings[] = {
145 "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16",
146 "VFPv4", "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
147 return parseStringAttribute("FP_arch", tag, ArrayRef(strings));
148}
149
150Error ARMAttributeParser::WMMX_arch(AttrType tag) {
151 static const char *const strings[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
152 return parseStringAttribute("WMMX_arch", tag, ArrayRef(strings));
153}
154
155Error ARMAttributeParser::Advanced_SIMD_arch(AttrType tag) {
156 static const char *const strings[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
157 "ARMv8-a NEON", "ARMv8.1-a NEON"};
158 return parseStringAttribute("Advanced_SIMD_arch", tag, ArrayRef(strings));
159}
160
161Error ARMAttributeParser::MVE_arch(AttrType tag) {
162 static const char *const strings[] = {"Not Permitted", "MVE integer",
163 "MVE integer and float"};
164 return parseStringAttribute("MVE_arch", tag, ArrayRef(strings));
165}
166
167Error ARMAttributeParser::PCS_config(AttrType tag) {
168 static const char *const strings[] = {"None",
169 "Bare Platform",
170 "Linux Application",
171 "Linux DSO",
172 "Palm OS 2004",
173 "Reserved (Palm OS)",
174 "Symbian OS 2004",
175 "Reserved (Symbian OS)"};
176 return parseStringAttribute("PCS_config", tag, ArrayRef(strings));
177}
178
179Error ARMAttributeParser::ABI_PCS_R9_use(AttrType tag) {
180 static const char *const strings[] = {"v6", "Static Base", "TLS", "Unused"};
181 return parseStringAttribute("ABI_PCS_R9_use", tag, ArrayRef(strings));
182}
183
184Error ARMAttributeParser::ABI_PCS_RW_data(AttrType tag) {
185 static const char *const strings[] = {"Absolute", "PC-relative",
186 "SB-relative", "Not Permitted"};
187 return parseStringAttribute("ABI_PCS_RW_data", tag, ArrayRef(strings));
188}
189
190Error ARMAttributeParser::ABI_PCS_RO_data(AttrType tag) {
191 static const char *const strings[] = {"Absolute", "PC-relative",
192 "Not Permitted"};
193 return parseStringAttribute("ABI_PCS_RO_data", tag, ArrayRef(strings));
194}
195
196Error ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag) {
197 static const char *const strings[] = {"Not Permitted", "Direct",
198 "GOT-Indirect"};
199 return parseStringAttribute("ABI_PCS_GOT_use", tag, ArrayRef(strings));
200}
201
202Error ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag) {
203 static const char *const strings[] = {"Not Permitted", "Unknown", "2-byte",
204 "Unknown", "4-byte"};
205 return parseStringAttribute("ABI_PCS_wchar_t", tag, ArrayRef(strings));
206}
207
208Error ARMAttributeParser::ABI_FP_rounding(AttrType tag) {
209 static const char *const strings[] = {"IEEE-754", "Runtime"};
210 return parseStringAttribute("ABI_FP_rounding", tag, ArrayRef(strings));
211}
212
213Error ARMAttributeParser::ABI_FP_denormal(AttrType tag) {
214 static const char *const strings[] = {"Unsupported", "IEEE-754", "Sign Only"};
215 return parseStringAttribute("ABI_FP_denormal", tag, ArrayRef(strings));
216}
217
218Error ARMAttributeParser::ABI_FP_exceptions(AttrType tag) {
219 static const char *const strings[] = {"Not Permitted", "IEEE-754"};
220 return parseStringAttribute("ABI_FP_exceptions", tag, ArrayRef(strings));
221}
222Error ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag) {
223 static const char *const strings[] = {"Not Permitted", "IEEE-754"};
224 return parseStringAttribute("ABI_FP_user_exceptions", tag, ArrayRef(strings));
225}
226
227Error ARMAttributeParser::ABI_FP_number_model(AttrType tag) {
228 static const char *const strings[] = {"Not Permitted", "Finite Only", "RTABI",
229 "IEEE-754"};
230 return parseStringAttribute("ABI_FP_number_model", tag, ArrayRef(strings));
231}
232
233Error ARMAttributeParser::ABI_align_needed(AttrType tag) {
234 static const char *const strings[] = {"Not Permitted", "8-byte alignment",
235 "4-byte alignment", "Reserved"};
236
238
239 std::string description;
240 if (value < std::size(strings))
241 description = strings[value];
242 else if (value <= 12)
243 description = "8-byte alignment, " + utostr(1ULL << value) +
244 "-byte extended alignment";
245 else
246 description = "Invalid";
247
248 printAttribute(tag, value, description);
249 return Error::success();
250}
251
252Error ARMAttributeParser::ABI_align_preserved(AttrType tag) {
253 static const char *strings[] = {"Not Required", "8-byte data alignment",
254 "8-byte data and code alignment", "Reserved"};
255
257
258 std::string description;
259 if (value < std::size(strings))
260 description = std::string(strings[value]);
261 else if (value <= 12)
262 description = std::string("8-byte stack alignment, ") +
263 utostr(1ULL << value) + std::string("-byte data alignment");
264 else
265 description = "Invalid";
266
267 printAttribute(tag, value, description);
268 return Error::success();
269}
270
271Error ARMAttributeParser::ABI_enum_size(AttrType tag) {
272 static const char *const strings[] = {"Not Permitted", "Packed", "Int32",
273 "External Int32"};
274 return parseStringAttribute("ABI_enum_size", tag, ArrayRef(strings));
275}
276
277Error ARMAttributeParser::ABI_HardFP_use(AttrType tag) {
278 static const char *const strings[] = {"Tag_FP_arch", "Single-Precision",
279 "Reserved", "Tag_FP_arch (deprecated)"};
280 return parseStringAttribute("ABI_HardFP_use", tag, ArrayRef(strings));
281}
282
283Error ARMAttributeParser::ABI_VFP_args(AttrType tag) {
284 static const char *const strings[] = {"AAPCS", "AAPCS VFP", "Custom",
285 "Not Permitted"};
286 return parseStringAttribute("ABI_VFP_args", tag, ArrayRef(strings));
287}
288
289Error ARMAttributeParser::ABI_WMMX_args(AttrType tag) {
290 static const char *const strings[] = {"AAPCS", "iWMMX", "Custom"};
291 return parseStringAttribute("ABI_WMMX_args", tag, ArrayRef(strings));
292}
293
294Error ARMAttributeParser::ABI_optimization_goals(AttrType tag) {
295 static const char *const strings[] = {
296 "None", "Speed", "Aggressive Speed",
297 "Size", "Aggressive Size", "Debugging",
298 "Best Debugging"};
299 return parseStringAttribute("ABI_optimization_goals", tag, ArrayRef(strings));
300}
301
302Error ARMAttributeParser::ABI_FP_optimization_goals(AttrType tag) {
303 static const char *const strings[] = {
304 "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size",
305 "Accuracy", "Best Accuracy"};
306 return parseStringAttribute("ABI_FP_optimization_goals", tag,
307 ArrayRef(strings));
308}
309
310Error ARMAttributeParser::compatibility(AttrType tag) {
311 uint64_t integer = de.getULEB128(cursor);
312 StringRef string = de.getCStrRef(cursor);
313
314 if (sw) {
315 DictScope scope(*sw, "Attribute");
316 sw->printNumber("Tag", tag);
317 sw->startLine() << "Value: " << integer << ", " << string << '\n';
318 sw->printString("TagName",
320 /*hasTagPrefix=*/false));
321 switch (integer) {
322 case 0:
323 sw->printString("Description", StringRef("No Specific Requirements"));
324 break;
325 case 1:
326 sw->printString("Description", StringRef("AEABI Conformant"));
327 break;
328 default:
329 sw->printString("Description", StringRef("AEABI Non-Conformant"));
330 break;
331 }
332 }
333 return Error::success();
334}
335
336Error ARMAttributeParser::CPU_unaligned_access(AttrType tag) {
337 static const char *const strings[] = {"Not Permitted", "v6-style"};
338 return parseStringAttribute("CPU_unaligned_access", tag, ArrayRef(strings));
339}
340
341Error ARMAttributeParser::FP_HP_extension(AttrType tag) {
342 static const char *const strings[] = {"If Available", "Permitted"};
343 return parseStringAttribute("FP_HP_extension", tag, ArrayRef(strings));
344}
345
346Error ARMAttributeParser::ABI_FP_16bit_format(AttrType tag) {
347 static const char *const strings[] = {"Not Permitted", "IEEE-754", "VFPv3"};
348 return parseStringAttribute("ABI_FP_16bit_format", tag, ArrayRef(strings));
349}
350
351Error ARMAttributeParser::MPextension_use(AttrType tag) {
352 static const char *const strings[] = {"Not Permitted", "Permitted"};
353 return parseStringAttribute("MPextension_use", tag, ArrayRef(strings));
354}
355
356Error ARMAttributeParser::DIV_use(AttrType tag) {
357 static const char *const strings[] = {"If Available", "Not Permitted",
358 "Permitted"};
359 return parseStringAttribute("DIV_use", tag, ArrayRef(strings));
360}
361
362Error ARMAttributeParser::DSP_extension(AttrType tag) {
363 static const char *const strings[] = {"Not Permitted", "Permitted"};
364 return parseStringAttribute("DSP_extension", tag, ArrayRef(strings));
365}
366
367Error ARMAttributeParser::T2EE_use(AttrType tag) {
368 static const char *const strings[] = {"Not Permitted", "Permitted"};
369 return parseStringAttribute("T2EE_use", tag, ArrayRef(strings));
370}
371
372Error ARMAttributeParser::Virtualization_use(AttrType tag) {
373 static const char *const strings[] = {
374 "Not Permitted", "TrustZone", "Virtualization Extensions",
375 "TrustZone + Virtualization Extensions"};
376 return parseStringAttribute("Virtualization_use", tag, ArrayRef(strings));
377}
378
379Error ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag) {
380 static const char *const strings[] = {"Not Permitted",
381 "Permitted in NOP space", "Permitted"};
382 return parseStringAttribute("PAC_extension", tag, ArrayRef(strings));
383}
384
385Error ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag) {
386 static const char *const strings[] = {"Not Permitted",
387 "Permitted in NOP space", "Permitted"};
388 return parseStringAttribute("BTI_extension", tag, ArrayRef(strings));
389}
390
391Error ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag) {
392 static const char *const strings[] = {"Not Used", "Used"};
393 return parseStringAttribute("PACRET_use", tag, ArrayRef(strings));
394}
395
396Error ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag) {
397 static const char *const strings[] = {"Not Used", "Used"};
398 return parseStringAttribute("BTI_use", tag, ArrayRef(strings));
399}
400
401Error ARMAttributeParser::nodefaults(AttrType tag) {
403 printAttribute(tag, value, "Unspecified Tags UNDEFINED");
404 return Error::success();
405}
406
407Error ARMAttributeParser::also_compatible_with(AttrType tag) {
408 // Parse value as a C string first in order to print it in escaped form later.
409 // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch.
410 std::optional<Error> returnValue;
411
412 SmallString<8> Description;
413 raw_svector_ostream DescStream(Description);
414
415 uint64_t InitialOffset = cursor.tell();
416 StringRef RawStringValue = de.getCStrRef(cursor);
417 uint64_t FinalOffset = cursor.tell();
418 cursor.seek(InitialOffset);
419 uint64_t InnerTag = de.getULEB128(cursor);
420
421 bool ValidInnerTag =
422 any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) {
423 return Item.attr == InnerTag;
424 });
425
426 if (!ValidInnerTag) {
427 returnValue =
429 Twine(InnerTag) + " is not a valid tag number");
430 } else {
431 switch (InnerTag) {
433 uint64_t InnerValue = de.getULEB128(cursor);
434 auto strings = ArrayRef(CPU_arch_strings);
435 if (InnerValue >= strings.size()) {
436 returnValue = createStringError(
438 Twine(InnerValue) + " is not a valid " +
440 " value");
441 } else {
442 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
443 << " = " << InnerValue;
444 if (strings[InnerValue])
445 DescStream << " (" << strings[InnerValue] << ')';
446 }
447 break;
448 }
450 returnValue = createStringError(
453 " cannot be recursively defined");
454 break;
459 StringRef InnerValue = de.getCStrRef(cursor);
460 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
461 << " = " << InnerValue;
462 break;
463 }
464 default: {
465 uint64_t InnerValue = de.getULEB128(cursor);
466 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
467 << " = " << InnerValue;
468 }
469 }
470 }
471
472 setAttributeString(tag, RawStringValue);
473 if (sw) {
474 DictScope scope(*sw, "Attribute");
475 sw->printNumber("Tag", tag);
476 sw->printString("TagName",
478 sw->printStringEscaped("Value", RawStringValue);
479 if (!Description.empty()) {
480 sw->printString("Description", Description);
481 }
482 }
483
484 cursor.seek(FinalOffset);
485
486 return returnValue ? std::move(*returnValue) : Error::success();
487}
488
489Error ARMAttributeParser::handler(uint64_t tag, bool &handled) {
490 handled = false;
491 for (const auto &AH : displayRoutines) {
492 if (uint64_t(AH.attribute) == tag) {
493 if (Error e = (this->*AH.routine)(static_cast<AttrType>(tag)))
494 return e;
495 handled = true;
496 break;
497 }
498 }
499
500 return Error::success();
501}
#define ATTRIBUTE_HANDLER(attr)
static const char *const CPU_arch_strings[]
Given that RA is a live value
This file contains some functions that are useful when dealing with strings.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
uint64_t tell() const
Return the current position of this Cursor.
Definition: DataExtractor.h:71
void seek(uint64_t NewOffSet)
Set the cursor to the new offset. This does not impact the error state.
Definition: DataExtractor.h:74
StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
void setAttributeString(unsigned tag, StringRef value)
DataExtractor::Cursor cursor
Error parseStringAttribute(const char *name, unsigned tag, ArrayRef< const char * > strings)
void printAttribute(unsigned tag, unsigned value, StringRef valueDesc)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
virtual void printString(StringRef Value)
void printStringEscaped(StringRef Label, StringRef Value)
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
bool empty() const
Definition: SmallVector.h:95
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap, bool hasTagPrefix=true)
constexpr double e
Definition: MathExtras.h:47
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1286
@ argument_out_of_domain
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1729