1e28b9357SCarlos Alberto Enciso //===-- LVSupport.cpp -----------------------------------------------------===// 2e28b9357SCarlos Alberto Enciso // 3e28b9357SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e28b9357SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 5e28b9357SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e28b9357SCarlos Alberto Enciso // 7e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===// 8e28b9357SCarlos Alberto Enciso // 9e28b9357SCarlos Alberto Enciso // This implements the supporting functions. 10e28b9357SCarlos Alberto Enciso // 11e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===// 12e28b9357SCarlos Alberto Enciso 13e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVSupport.h" 14e28b9357SCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h" 15e28b9357SCarlos Alberto Enciso 16e28b9357SCarlos Alberto Enciso using namespace llvm; 17e28b9357SCarlos Alberto Enciso using namespace llvm::logicalview; 18e28b9357SCarlos Alberto Enciso 19e28b9357SCarlos Alberto Enciso #define DEBUG_TYPE "Support" 20e28b9357SCarlos Alberto Enciso 2192716a42SCarlos Alberto Enciso namespace { 2292716a42SCarlos Alberto Enciso // Unique string pool instance used by all logical readers. 2392716a42SCarlos Alberto Enciso LVStringPool StringPool; 2492716a42SCarlos Alberto Enciso } // namespace 2592716a42SCarlos Alberto Enciso LVStringPool &llvm::logicalview::getStringPool() { return StringPool; } 2692716a42SCarlos Alberto Enciso 27e28b9357SCarlos Alberto Enciso // Perform the following transformations to the given 'Path': 28e28b9357SCarlos Alberto Enciso // - all characters to lowercase. 29e28b9357SCarlos Alberto Enciso // - '\\' into '/' (Platform independent). 30e28b9357SCarlos Alberto Enciso // - '//' into '/' 31e28b9357SCarlos Alberto Enciso std::string llvm::logicalview::transformPath(StringRef Path) { 32e28b9357SCarlos Alberto Enciso std::string Name(Path); 33e28b9357SCarlos Alberto Enciso std::transform(Name.begin(), Name.end(), Name.begin(), tolower); 34e28b9357SCarlos Alberto Enciso std::replace(Name.begin(), Name.end(), '\\', '/'); 35e28b9357SCarlos Alberto Enciso 36e28b9357SCarlos Alberto Enciso // Remove all duplicate slashes. 37e28b9357SCarlos Alberto Enciso size_t Pos = 0; 38e28b9357SCarlos Alberto Enciso while ((Pos = Name.find("//", Pos)) != std::string::npos) 39e28b9357SCarlos Alberto Enciso Name.erase(Pos, 1); 40e28b9357SCarlos Alberto Enciso 41e28b9357SCarlos Alberto Enciso return Name; 42e28b9357SCarlos Alberto Enciso } 43e28b9357SCarlos Alberto Enciso 44e28b9357SCarlos Alberto Enciso // Convert the given 'Path' to lowercase and change any matching character 45e28b9357SCarlos Alberto Enciso // from 'CharSet' into '_'. 46e28b9357SCarlos Alberto Enciso // The characters in 'CharSet' are: 47e28b9357SCarlos Alberto Enciso // '/', '\', '<', '>', '.', ':', '%', '*', '?', '|', '"', ' '. 48e28b9357SCarlos Alberto Enciso std::string llvm::logicalview::flattenedFilePath(StringRef Path) { 49e28b9357SCarlos Alberto Enciso std::string Name(Path); 50e28b9357SCarlos Alberto Enciso std::transform(Name.begin(), Name.end(), Name.begin(), tolower); 51e28b9357SCarlos Alberto Enciso 52e28b9357SCarlos Alberto Enciso const char *CharSet = "/\\<>.:%*?|\" "; 53e28b9357SCarlos Alberto Enciso char *Input = Name.data(); 54e28b9357SCarlos Alberto Enciso while (Input && *Input) { 55e28b9357SCarlos Alberto Enciso Input = strpbrk(Input, CharSet); 56e28b9357SCarlos Alberto Enciso if (Input) 57e28b9357SCarlos Alberto Enciso *Input++ = '_'; 58e28b9357SCarlos Alberto Enciso }; 59e28b9357SCarlos Alberto Enciso return Name; 60e28b9357SCarlos Alberto Enciso } 61*e7950fceSCarlos Alberto Enciso 62*e7950fceSCarlos Alberto Enciso using LexicalEntry = std::pair<size_t, size_t>; 63*e7950fceSCarlos Alberto Enciso using LexicalIndexes = SmallVector<LexicalEntry, 10>; 64*e7950fceSCarlos Alberto Enciso 65*e7950fceSCarlos Alberto Enciso static LexicalIndexes getAllLexicalIndexes(StringRef Name) { 66*e7950fceSCarlos Alberto Enciso if (Name.empty()) 67*e7950fceSCarlos Alberto Enciso return {}; 68*e7950fceSCarlos Alberto Enciso 69*e7950fceSCarlos Alberto Enciso size_t AngleCount = 0; 70*e7950fceSCarlos Alberto Enciso size_t ColonSeen = 0; 71*e7950fceSCarlos Alberto Enciso size_t Current = 0; 72*e7950fceSCarlos Alberto Enciso 73*e7950fceSCarlos Alberto Enciso LexicalIndexes Indexes; 74*e7950fceSCarlos Alberto Enciso 75*e7950fceSCarlos Alberto Enciso #ifndef NDEBUG 76*e7950fceSCarlos Alberto Enciso auto PrintLexicalEntry = [&]() { 77*e7950fceSCarlos Alberto Enciso LexicalEntry Entry = Indexes.back(); 78*e7950fceSCarlos Alberto Enciso llvm::dbgs() << formatv( 79*e7950fceSCarlos Alberto Enciso "'{0}:{1}', '{2}'\n", Entry.first, Entry.second, 80*e7950fceSCarlos Alberto Enciso Name.substr(Entry.first, Entry.second - Entry.first + 1)); 81*e7950fceSCarlos Alberto Enciso }; 82*e7950fceSCarlos Alberto Enciso #endif 83*e7950fceSCarlos Alberto Enciso 84*e7950fceSCarlos Alberto Enciso size_t Length = Name.size(); 85*e7950fceSCarlos Alberto Enciso for (size_t Index = 0; Index < Length; ++Index) { 86*e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 87*e7950fceSCarlos Alberto Enciso llvm::dbgs() << formatv("Index: '{0}', Char: '{1}'\n", Index, 88*e7950fceSCarlos Alberto Enciso Name[Index]); 89*e7950fceSCarlos Alberto Enciso }); 90*e7950fceSCarlos Alberto Enciso switch (Name[Index]) { 91*e7950fceSCarlos Alberto Enciso case '<': 92*e7950fceSCarlos Alberto Enciso ++AngleCount; 93*e7950fceSCarlos Alberto Enciso break; 94*e7950fceSCarlos Alberto Enciso case '>': 95*e7950fceSCarlos Alberto Enciso --AngleCount; 96*e7950fceSCarlos Alberto Enciso break; 97*e7950fceSCarlos Alberto Enciso case ':': 98*e7950fceSCarlos Alberto Enciso ++ColonSeen; 99*e7950fceSCarlos Alberto Enciso break; 100*e7950fceSCarlos Alberto Enciso } 101*e7950fceSCarlos Alberto Enciso if (ColonSeen == 2) { 102*e7950fceSCarlos Alberto Enciso if (!AngleCount) { 103*e7950fceSCarlos Alberto Enciso Indexes.push_back(LexicalEntry(Current, Index - 2)); 104*e7950fceSCarlos Alberto Enciso Current = Index + 1; 105*e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ PrintLexicalEntry(); }); 106*e7950fceSCarlos Alberto Enciso } 107*e7950fceSCarlos Alberto Enciso ColonSeen = 0; 108*e7950fceSCarlos Alberto Enciso continue; 109*e7950fceSCarlos Alberto Enciso } 110*e7950fceSCarlos Alberto Enciso } 111*e7950fceSCarlos Alberto Enciso 112*e7950fceSCarlos Alberto Enciso // Store last component. 113*e7950fceSCarlos Alberto Enciso Indexes.push_back(LexicalEntry(Current, Length - 1)); 114*e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ PrintLexicalEntry(); }); 115*e7950fceSCarlos Alberto Enciso return Indexes; 116*e7950fceSCarlos Alberto Enciso } 117*e7950fceSCarlos Alberto Enciso 118*e7950fceSCarlos Alberto Enciso LVLexicalComponent llvm::logicalview::getInnerComponent(StringRef Name) { 119*e7950fceSCarlos Alberto Enciso if (Name.empty()) 120*e7950fceSCarlos Alberto Enciso return {}; 121*e7950fceSCarlos Alberto Enciso 122*e7950fceSCarlos Alberto Enciso LexicalIndexes Indexes = getAllLexicalIndexes(Name); 123*e7950fceSCarlos Alberto Enciso if (Indexes.size() == 1) 124*e7950fceSCarlos Alberto Enciso return std::make_tuple(StringRef(), Name); 125*e7950fceSCarlos Alberto Enciso 126*e7950fceSCarlos Alberto Enciso LexicalEntry BeginEntry = Indexes.front(); 127*e7950fceSCarlos Alberto Enciso LexicalEntry EndEntry = Indexes[Indexes.size() - 2]; 128*e7950fceSCarlos Alberto Enciso StringRef Outer = 129*e7950fceSCarlos Alberto Enciso Name.substr(BeginEntry.first, EndEntry.second - BeginEntry.first + 1); 130*e7950fceSCarlos Alberto Enciso 131*e7950fceSCarlos Alberto Enciso LexicalEntry LastEntry = Indexes.back(); 132*e7950fceSCarlos Alberto Enciso StringRef Inner = 133*e7950fceSCarlos Alberto Enciso Name.substr(LastEntry.first, LastEntry.second - LastEntry.first + 1); 134*e7950fceSCarlos Alberto Enciso 135*e7950fceSCarlos Alberto Enciso return std::make_tuple(Outer, Inner); 136*e7950fceSCarlos Alberto Enciso } 137*e7950fceSCarlos Alberto Enciso 138*e7950fceSCarlos Alberto Enciso LVStringRefs llvm::logicalview::getAllLexicalComponents(StringRef Name) { 139*e7950fceSCarlos Alberto Enciso if (Name.empty()) 140*e7950fceSCarlos Alberto Enciso return {}; 141*e7950fceSCarlos Alberto Enciso 142*e7950fceSCarlos Alberto Enciso LexicalIndexes Indexes = getAllLexicalIndexes(Name); 143*e7950fceSCarlos Alberto Enciso LVStringRefs Components; 144*e7950fceSCarlos Alberto Enciso for (const LexicalEntry &Entry : Indexes) 145*e7950fceSCarlos Alberto Enciso Components.push_back( 146*e7950fceSCarlos Alberto Enciso Name.substr(Entry.first, Entry.second - Entry.first + 1)); 147*e7950fceSCarlos Alberto Enciso 148*e7950fceSCarlos Alberto Enciso return Components; 149*e7950fceSCarlos Alberto Enciso } 150*e7950fceSCarlos Alberto Enciso 151*e7950fceSCarlos Alberto Enciso std::string llvm::logicalview::getScopedName(const LVStringRefs &Components, 152*e7950fceSCarlos Alberto Enciso StringRef BaseName) { 153*e7950fceSCarlos Alberto Enciso if (Components.empty()) 154*e7950fceSCarlos Alberto Enciso return {}; 155*e7950fceSCarlos Alberto Enciso std::string Name(BaseName); 156*e7950fceSCarlos Alberto Enciso raw_string_ostream Stream(Name); 157*e7950fceSCarlos Alberto Enciso if (BaseName.size()) 158*e7950fceSCarlos Alberto Enciso Stream << "::"; 159*e7950fceSCarlos Alberto Enciso Stream << Components[0]; 160*e7950fceSCarlos Alberto Enciso for (LVStringRefs::size_type Index = 1; Index < Components.size(); ++Index) 161*e7950fceSCarlos Alberto Enciso Stream << "::" << Components[Index]; 162*e7950fceSCarlos Alberto Enciso return Name; 163*e7950fceSCarlos Alberto Enciso } 164