LLVM 22.0.0git
LVReader.cpp
Go to the documentation of this file.
1//===-- LVReader.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//
9// This implements the LVReader class.
10//
11//===----------------------------------------------------------------------===//
12
18#include <tuple>
19
20using namespace llvm;
21using namespace llvm::logicalview;
22
23#define DEBUG_TYPE "Reader"
24
25// Detect elements that are inserted more than once at different scopes,
26// causing a crash on the reader destruction, as the element is already
27// deleted from other scope. Helper for CodeView reader.
29 using LVDuplicateEntry = std::tuple<LVElement *, LVScope *, LVScope *>;
30 using LVDuplicate = std::vector<LVDuplicateEntry>;
31 LVDuplicate Duplicate;
32
33 using LVIntegrity = std::map<LVElement *, LVScope *>;
34 LVIntegrity Integrity;
35
36 // Add the given element to the integrity map.
37 auto AddElement = [&](LVElement *Element, LVScope *Scope) {
38 LVIntegrity::iterator Iter = Integrity.find(Element);
39 if (Iter == Integrity.end())
40 Integrity.emplace(Element, Scope);
41 else
42 // We found a duplicate.
43 Duplicate.emplace_back(Element, Scope, Iter->second);
44 };
45
46 // Recursively add all the elements in the scope.
47 std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
48 auto Traverse = [&](const auto *Set) {
49 if (Set)
50 for (const auto &Entry : *Set)
51 AddElement(Entry, Parent);
52 };
53 if (const LVScopes *Scopes = Parent->getScopes()) {
54 for (LVScope *Scope : *Scopes) {
55 AddElement(Scope, Parent);
56 TraverseScope(Scope);
57 }
58 }
59 Traverse(Parent->getSymbols());
60 Traverse(Parent->getTypes());
61 Traverse(Parent->getLines());
62 };
63
64 // Start traversing the scopes root and print any duplicates.
65 TraverseScope(Root);
66 bool PassIntegrity = true;
67 if (Duplicate.size()) {
68 llvm::stable_sort(Duplicate, [](const auto &l, const auto &r) {
69 return std::get<0>(l)->getID() < std::get<0>(r)->getID();
70 });
71
72 auto PrintIndex = [](unsigned Index) {
73 if (Index)
74 dbgs() << format("%8d: ", Index);
75 else
76 dbgs() << format("%8c: ", ' ');
77 };
78 auto PrintElement = [&](LVElement *Element, unsigned Index = 0) {
79 PrintIndex(Index);
80 std::string ElementName(Element->getName());
81 dbgs() << format("%15s ID=0x%08x '%s'\n", Element->kind(),
82 Element->getID(), ElementName.c_str());
83 };
84
85 std::string RootName(Root->getName());
86 dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
87 dbgs() << format("Root: '%s'\nDuplicated elements: %d\n", RootName.c_str(),
88 Duplicate.size());
89 dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
90
91 unsigned Index = 0;
92 for (const LVDuplicateEntry &Entry : Duplicate) {
93 LVElement *Element;
95 LVScope *Second;
96 std::tie(Element, First, Second) = Entry;
97 dbgs() << formatv("\n{0}\n", fmt_repeat('-', 72));
98 PrintElement(Element, ++Index);
99 PrintElement(First);
100 PrintElement(Second);
101 dbgs() << formatv("{0}\n", fmt_repeat('-', 72));
102 }
103 PassIntegrity = false;
104 }
105 return PassIntegrity;
106}
107
108//===----------------------------------------------------------------------===//
109// Class to represent a split context.
110//===----------------------------------------------------------------------===//
112 // The 'location' will represent the root directory for the output created
113 // by the context. It will contain the different CUs files, that will be
114 // extracted from a single ELF.
115 Location = std::string(Where);
116
117 // Add a trailing slash, if there is none.
118 size_t Pos = Location.find_last_of('/');
119 if (Location.length() != Pos + 1)
120 Location.append("/");
121
122 // Make sure the new directory exists, creating it if necessary.
123 if (std::error_code EC = llvm::sys::fs::create_directories(Location))
124 return createStringError(EC, "Error: could not create directory %s",
125 Location.c_str());
126
127 return Error::success();
128}
129
130std::error_code LVSplitContext::open(std::string ContextName,
131 std::string Extension, raw_ostream &OS) {
132 assert(OutputFile == nullptr && "OutputFile already set.");
133
134 // Transforms '/', '\', '.', ':' into '_'.
135 std::string Name(flattenedFilePath(ContextName));
136 Name.append(Extension);
137 // Add the split context location folder name.
138 if (!Location.empty())
139 Name.insert(0, Location);
140
141 std::error_code EC;
142 OutputFile = std::make_unique<ToolOutputFile>(Name, EC, sys::fs::OF_None);
143 if (EC)
144 return EC;
145
146 // Don't remove output file.
147 OutputFile->keep();
148 return std::error_code();
149}
150
153 if (CurrentReader)
154 return *CurrentReader;
155 outs() << "Invalid instance reader.\n";
156 llvm_unreachable("Invalid instance reader.");
157}
159
160Error LVReader::createSplitFolder() {
161 if (OutputSplit) {
162 // If the '--output=split' was specified, but no '--split-folder'
163 // option, use the input file as base for the split location.
164 if (options().getOutputFolder().empty())
165 options().setOutputFolder(getFilename().str() + "_cus");
166
167 SmallString<128> SplitFolder;
168 SplitFolder = options().getOutputFolder();
169 sys::fs::make_absolute(SplitFolder);
170
171 // Return error if unable to create a split context location.
172 if (Error Err = SplitContext.createSplitFolder(SplitFolder))
173 return Err;
174
175 OS << "\nSplit View Location: '" << SplitContext.getLocation() << "'\n";
176 }
177
178 return Error::success();
179}
180
181// Get the filename for given object.
182StringRef LVReader::getFilename(LVObject *Object, size_t Index) const {
183 // TODO: The current CodeView Reader implementation does not have support
184 // for multiple compile units. Until we have a proper offset calculation,
185 // check only in the current compile unit.
186 if (CompileUnits.size()) {
187 // Get Compile Unit for the given object.
188 LVCompileUnits::const_iterator Iter =
189 std::prev(CompileUnits.lower_bound(Object->getOffset()));
190 if (Iter != CompileUnits.end())
191 return Iter->second->getFilename(Index);
192 }
193
194 return CompileUnit ? CompileUnit->getFilename(Index) : StringRef();
195}
196
198 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
199 ScopesWithRanges->addEntry(Scope);
200}
201
203 LVAddress LowerAddress, LVAddress UpperAddress) {
204 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
205 ScopesWithRanges->addEntry(Scope, LowerAddress, UpperAddress);
206}
207
209 // Check if we already have a mapping for this section index.
210 LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex);
211 if (IterSection == SectionRanges.end())
212 IterSection =
213 SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first;
214 LVRange *Range = IterSection->second.get();
215 assert(Range && "Range is null.");
216 return Range;
217}
218
220 CurrentScope = nullptr;
221 CurrentSymbol = nullptr;
222 CurrentType = nullptr;
223 CurrentRanges.clear();
224
226 { dbgs() << "\n[createElement] " << dwarf::TagString(Tag) << "\n"; });
227
228 if (!options().getPrintSymbols()) {
229 switch (Tag) {
230 // As the command line options did not specify a request to print
231 // logical symbols (--print=symbols or --print=all or --print=elements),
232 // skip its creation.
233 case dwarf::DW_TAG_formal_parameter:
234 case dwarf::DW_TAG_unspecified_parameters:
235 case dwarf::DW_TAG_member:
236 case dwarf::DW_TAG_variable:
237 case dwarf::DW_TAG_inheritance:
238 case dwarf::DW_TAG_constant:
239 case dwarf::DW_TAG_call_site_parameter:
240 case dwarf::DW_TAG_GNU_call_site_parameter:
241 return nullptr;
242 default:
243 break;
244 }
245 }
246
247 switch (Tag) {
248 // Types.
249 case dwarf::DW_TAG_base_type:
250 CurrentType = createType();
251 CurrentType->setIsBase();
252 if (options().getAttributeBase())
253 CurrentType->setIncludeInPrint();
254 return CurrentType;
255 case dwarf::DW_TAG_const_type:
256 CurrentType = createType();
257 CurrentType->setIsConst();
258 CurrentType->setName("const");
259 return CurrentType;
260 case dwarf::DW_TAG_enumerator:
261 CurrentType = createTypeEnumerator();
262 return CurrentType;
263 case dwarf::DW_TAG_imported_declaration:
264 CurrentType = createTypeImport();
265 CurrentType->setIsImportDeclaration();
266 return CurrentType;
267 case dwarf::DW_TAG_imported_module:
268 CurrentType = createTypeImport();
269 CurrentType->setIsImportModule();
270 return CurrentType;
271 case dwarf::DW_TAG_pointer_type:
272 CurrentType = createType();
273 CurrentType->setIsPointer();
274 CurrentType->setName("*");
275 return CurrentType;
276 case dwarf::DW_TAG_ptr_to_member_type:
277 CurrentType = createType();
278 CurrentType->setIsPointerMember();
279 CurrentType->setName("*");
280 return CurrentType;
281 case dwarf::DW_TAG_reference_type:
282 CurrentType = createType();
283 CurrentType->setIsReference();
284 CurrentType->setName("&");
285 return CurrentType;
286 case dwarf::DW_TAG_restrict_type:
287 CurrentType = createType();
288 CurrentType->setIsRestrict();
289 CurrentType->setName("restrict");
290 return CurrentType;
291 case dwarf::DW_TAG_rvalue_reference_type:
292 CurrentType = createType();
293 CurrentType->setIsRvalueReference();
294 CurrentType->setName("&&");
295 return CurrentType;
296 case dwarf::DW_TAG_subrange_type:
297 CurrentType = createTypeSubrange();
298 return CurrentType;
299 case dwarf::DW_TAG_template_value_parameter:
300 CurrentType = createTypeParam();
301 CurrentType->setIsTemplateValueParam();
302 return CurrentType;
303 case dwarf::DW_TAG_template_type_parameter:
304 CurrentType = createTypeParam();
305 CurrentType->setIsTemplateTypeParam();
306 return CurrentType;
307 case dwarf::DW_TAG_GNU_template_template_param:
308 CurrentType = createTypeParam();
309 CurrentType->setIsTemplateTemplateParam();
310 return CurrentType;
311 case dwarf::DW_TAG_typedef:
312 CurrentType = createTypeDefinition();
313 return CurrentType;
314 case dwarf::DW_TAG_unspecified_type:
315 CurrentType = createType();
316 CurrentType->setIsUnspecified();
317 return CurrentType;
318 case dwarf::DW_TAG_volatile_type:
319 CurrentType = createType();
320 CurrentType->setIsVolatile();
321 CurrentType->setName("volatile");
322 return CurrentType;
323
324 // Symbols.
325 case dwarf::DW_TAG_formal_parameter:
326 CurrentSymbol = createSymbol();
327 CurrentSymbol->setIsParameter();
328 return CurrentSymbol;
329 case dwarf::DW_TAG_unspecified_parameters:
330 CurrentSymbol = createSymbol();
331 CurrentSymbol->setIsUnspecified();
332 CurrentSymbol->setName("...");
333 return CurrentSymbol;
334 case dwarf::DW_TAG_member:
335 CurrentSymbol = createSymbol();
336 CurrentSymbol->setIsMember();
337 return CurrentSymbol;
338 case dwarf::DW_TAG_variable:
339 CurrentSymbol = createSymbol();
340 CurrentSymbol->setIsVariable();
341 return CurrentSymbol;
342 case dwarf::DW_TAG_inheritance:
343 CurrentSymbol = createSymbol();
344 CurrentSymbol->setIsInheritance();
345 return CurrentSymbol;
346 case dwarf::DW_TAG_call_site_parameter:
347 case dwarf::DW_TAG_GNU_call_site_parameter:
348 CurrentSymbol = createSymbol();
349 CurrentSymbol->setIsCallSiteParameter();
350 return CurrentSymbol;
351 case dwarf::DW_TAG_constant:
352 CurrentSymbol = createSymbol();
353 CurrentSymbol->setIsConstant();
354 return CurrentSymbol;
355
356 // Scopes.
357 case dwarf::DW_TAG_catch_block:
358 CurrentScope = createScope();
359 CurrentScope->setIsCatchBlock();
360 return CurrentScope;
361 case dwarf::DW_TAG_lexical_block:
362 CurrentScope = createScope();
363 CurrentScope->setIsLexicalBlock();
364 return CurrentScope;
365 case dwarf::DW_TAG_try_block:
366 CurrentScope = createScope();
367 CurrentScope->setIsTryBlock();
368 return CurrentScope;
369 case dwarf::DW_TAG_compile_unit:
370 case dwarf::DW_TAG_skeleton_unit:
371 CurrentScope = createScopeCompileUnit();
373 return CurrentScope;
374 case dwarf::DW_TAG_inlined_subroutine:
375 CurrentScope = createScopeFunctionInlined();
376 return CurrentScope;
377 case dwarf::DW_TAG_namespace:
378 CurrentScope = createScopeNamespace();
379 return CurrentScope;
380 case dwarf::DW_TAG_template_alias:
381 CurrentScope = createScopeAlias();
382 return CurrentScope;
383 case dwarf::DW_TAG_array_type:
384 CurrentScope = createScopeArray();
385 return CurrentScope;
386 case dwarf::DW_TAG_call_site:
387 case dwarf::DW_TAG_GNU_call_site:
388 CurrentScope = createScopeFunction();
389 CurrentScope->setIsCallSite();
390 return CurrentScope;
391 case dwarf::DW_TAG_entry_point:
392 CurrentScope = createScopeFunction();
393 CurrentScope->setIsEntryPoint();
394 return CurrentScope;
395 case dwarf::DW_TAG_subprogram:
396 CurrentScope = createScopeFunction();
397 CurrentScope->setIsSubprogram();
398 return CurrentScope;
399 case dwarf::DW_TAG_subroutine_type:
400 CurrentScope = createScopeFunctionType();
401 return CurrentScope;
402 case dwarf::DW_TAG_label:
403 CurrentScope = createScopeFunction();
404 CurrentScope->setIsLabel();
405 return CurrentScope;
406 case dwarf::DW_TAG_class_type:
407 CurrentScope = createScopeAggregate();
408 CurrentScope->setIsClass();
409 return CurrentScope;
410 case dwarf::DW_TAG_structure_type:
411 CurrentScope = createScopeAggregate();
412 CurrentScope->setIsStructure();
413 return CurrentScope;
414 case dwarf::DW_TAG_union_type:
415 CurrentScope = createScopeAggregate();
416 CurrentScope->setIsUnion();
417 return CurrentScope;
418 case dwarf::DW_TAG_enumeration_type:
419 CurrentScope = createScopeEnumeration();
420 return CurrentScope;
421 case dwarf::DW_TAG_GNU_formal_parameter_pack:
422 CurrentScope = createScopeFormalPack();
423 return CurrentScope;
424 case dwarf::DW_TAG_GNU_template_parameter_pack:
425 CurrentScope = createScopeTemplatePack();
426 return CurrentScope;
427 case dwarf::DW_TAG_module:
428 CurrentScope = createScopeModule();
429 return CurrentScope;
430 default:
431 // Collect TAGs not implemented.
432 if (options().getInternalTag() && Tag)
433 CompileUnit->addDebugTag(Tag, CurrentOffset);
434 break;
435 }
436
437 LLVM_DEBUG({
438 dbgs() << "DWARF Tag not implemented: " << dwarf::TagString(Tag) << "\n";
439 });
440
441 return nullptr;
442}
443
444// The Reader is the module that creates the logical view using the debug
445// information contained in the binary file specified in the command line.
446// This is the main entry point for the Reader and performs the following
447// steps:
448// - Process any patterns collected from the '--select' options.
449// - For each compile unit in the debug information:
450// * Create the logical elements (scopes, symbols, types, lines).
451// * Collect debug ranges and debug locations.
452// * Move the collected logical lines to their associated scopes.
453// - Once all the compile units have been processed, traverse the scopes
454// tree in order to:
455// * Calculate symbol coverage.
456// * Detect invalid ranges and locations.
457// * "resolve" the logical elements. During this pass, the names and
458// file information are updated, to reflect any dependency with other
459// logical elements.
461 // Set current Reader instance.
462 setInstance(this);
463
464 // Before any scopes creation, process any pattern specified by the
465 // --select and --select-offsets options.
468
469 // Add any specific element printing requests based on the element kind.
470 patterns().addRequest(options().Select.Elements);
471 patterns().addRequest(options().Select.Lines);
472 patterns().addRequest(options().Select.Scopes);
473 patterns().addRequest(options().Select.Symbols);
474 patterns().addRequest(options().Select.Types);
475
476 // Once we have processed the requests for any particular kind of elements,
477 // we need to update the report options, in order to have a default value.
479
480 // Delegate the scope tree creation to the specific reader.
481 if (Error Err = createScopes())
482 return Err;
483
484 if (options().getInternalIntegrity() && !checkIntegrityScopesTree(Root))
485 return llvm::make_error<StringError>("Duplicated elements in Scopes Tree",
487
488 // Calculate symbol coverage and detect invalid debug locations and ranges.
490
491 // As the elements can depend on elements from a different compile unit,
492 // information such as name and file/line source information needs to be
493 // updated.
495
496 sortScopes();
497 return Error::success();
498}
499
500// Default handler for a generic reader.
502 // Set current Reader instance.
503 setInstance(this);
504
505 // Check for any '--report' request.
506 if (options().getReportExecute()) {
507 // Requested details.
508 if (options().getReportList())
509 if (Error Err = printMatchedElements(/*UseMatchedElements=*/true))
510 return Err;
511 // Requested only children.
512 if (options().getReportChildren() && !options().getReportParents())
513 if (Error Err = printMatchedElements(/*UseMatchedElements=*/false))
514 return Err;
515 // Requested (parents) or (parents and children).
516 if (options().getReportParents() || options().getReportView())
517 if (Error Err = printScopes())
518 return Err;
519
520 return Error::success();
521 }
522
523 return printScopes();
524}
525
527 if (bool DoPrint =
528 (options().getPrintExecute() || options().getComparePrint())) {
529 if (Error Err = createSplitFolder())
530 return Err;
531
532 // Start printing from the root.
533 bool DoMatch = options().getSelectGenericPattern() ||
534 options().getSelectGenericKind() ||
535 options().getSelectOffsetPattern();
536 return Root->doPrint(OutputSplit, DoMatch, DoPrint, OS);
537 }
538
539 return Error::success();
540}
541
542Error LVReader::printMatchedElements(bool UseMatchedElements) {
543 if (Error Err = createSplitFolder())
544 return Err;
545
546 return Root->doPrintMatches(OutputSplit, OS, UseMatchedElements);
547}
548
550 OS << "LVReader\n";
551 LLVM_DEBUG(dbgs() << "PrintReader\n");
552}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
LVReader * CurrentReader
Definition: LVReader.cpp:151
bool checkIntegrityScopesTree(LVScope *Root)
Definition: LVReader.cpp:28
raw_pwrite_stream & OS
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
static ErrorSuccess success()
Create a success value.
Definition: Error.h:336
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Stores all information relating to a compile unit, be it in its original instance in the object file ...
void setName(StringRef ElementName) override
Definition: LVElement.cpp:95
StringRef getName() const override
Definition: LVElement.h:192
uint32_t getID() const
Definition: LVObject.h:319
virtual const char * kind() const
Definition: LVObject.h:276
LLVM_ABI void addGenericPatterns(StringSet<> &Patterns)
Definition: LVOptions.cpp:441
LLVM_ABI void updateReportOptions()
Definition: LVOptions.cpp:491
LLVM_ABI void addOffsetPatterns(const LVOffsetSet &Patterns)
Definition: LVOptions.cpp:449
void addEntry(LVScope *Scope, LVAddress LowerAddress, LVAddress UpperAddress)
Definition: LVRange.cpp:52
The logical reader owns of all the logical elements created during the debug information parsing.
Definition: LVReader.h:61
virtual void sortScopes()
Definition: LVReader.h:194
LVRange * getSectionRanges(LVSectionIndex SectionIndex)
Definition: LVReader.cpp:208
void print(raw_ostream &OS) const
Definition: LVReader.cpp:549
std::vector< LVAddressRange > CurrentRanges
Definition: LVReader.h:142
LVElement * createElement(dwarf::Tag Tag)
Definition: LVReader.cpp:219
StringRef getFilename() const
Definition: LVReader.h:263
static LVReader & getInstance()
Definition: LVReader.cpp:152
static void setInstance(LVReader *Reader)
Definition: LVReader.cpp:158
void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope)
Definition: LVReader.cpp:197
virtual Error printMatchedElements(bool UseMatchedElements)
Definition: LVReader.cpp:542
virtual Error printScopes()
Definition: LVReader.cpp:526
virtual Error createScopes()
Definition: LVReader.h:167
Error doPrintMatches(bool Split, raw_ostream &OS, bool UseMatchedElements) const
Definition: LVScope.cpp:2088
const LVLines * getLines() const
Definition: LVScope.h:211
const LVScopes * getScopes() const
Definition: LVScope.h:213
const LVSymbols * getSymbols() const
Definition: LVScope.h:214
const LVTypes * getTypes() const
Definition: LVScope.h:215
Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, bool Full=true) const override
Definition: LVScope.cpp:585
std::string getLocation() const
Definition: LVReader.h:54
LLVM_ABI Error createSplitFolder(StringRef Where)
Definition: LVReader.cpp:111
LLVM_ABI std::error_code open(std::string Name, std::string Extension, raw_ostream &OS)
Definition: LVReader.cpp:130
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
LLVM_ABI StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:21
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LVPatterns & patterns()
Definition: LVOptions.h:645
LLVM_ABI std::string flattenedFilePath(StringRef Path)
Definition: LVSupport.cpp:48
LVOptions & options()
Definition: LVOptions.h:448
LLVM_ABI void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:906
LLVM_ABI std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:967
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void stable_sort(R &&Range)
Definition: STLExtras.h:2077
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1305
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:126
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
support::detail::RepeatAdapter< T > fmt_repeat(T &&Item, size_t Count)