Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:43

0001 //===-- LVSupport.h ---------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines support functions.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
0014 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
0015 
0016 #include "llvm/ADT/SmallBitVector.h"
0017 #include "llvm/ADT/Twine.h"
0018 #include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
0019 #include "llvm/Support/Debug.h"
0020 #include "llvm/Support/Format.h"
0021 #include "llvm/Support/Path.h"
0022 #include "llvm/Support/raw_ostream.h"
0023 #include <cctype>
0024 #include <map>
0025 #include <sstream>
0026 
0027 namespace llvm {
0028 namespace logicalview {
0029 
0030 // Returns the unique string pool instance.
0031 LVStringPool &getStringPool();
0032 
0033 using LVStringRefs = std::vector<StringRef>;
0034 using LVLexicalComponent = std::tuple<StringRef, StringRef>;
0035 using LVLexicalIndex =
0036     std::tuple<LVStringRefs::size_type, LVStringRefs::size_type>;
0037 
0038 // Used to record specific characteristics about the objects.
0039 template <typename T> class LVProperties {
0040   SmallBitVector Bits = SmallBitVector(static_cast<unsigned>(T::LastEntry) + 1);
0041 
0042 public:
0043   LVProperties() = default;
0044 
0045   void set(T Idx) { Bits[static_cast<unsigned>(Idx)] = 1; }
0046   void reset(T Idx) { Bits[static_cast<unsigned>(Idx)] = 0; }
0047   bool get(T Idx) const { return Bits[static_cast<unsigned>(Idx)]; }
0048 };
0049 
0050 // Generate get, set and reset 'bool' functions for LVProperties instances.
0051 // FAMILY: instance name.
0052 // ENUM: enumeration instance.
0053 // FIELD: enumerator instance.
0054 // F1, F2, F3: optional 'set' functions to be called.
0055 #define BOOL_BIT(FAMILY, ENUM, FIELD)                                          \
0056   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
0057   void set##FIELD() { FAMILY.set(ENUM::FIELD); }                               \
0058   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
0059 
0060 #define BOOL_BIT_1(FAMILY, ENUM, FIELD, F1)                                    \
0061   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
0062   void set##FIELD() {                                                          \
0063     FAMILY.set(ENUM::FIELD);                                                   \
0064     set##F1();                                                                 \
0065   }                                                                            \
0066   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
0067 
0068 #define BOOL_BIT_2(FAMILY, ENUM, FIELD, F1, F2)                                \
0069   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
0070   void set##FIELD() {                                                          \
0071     FAMILY.set(ENUM::FIELD);                                                   \
0072     set##F1();                                                                 \
0073     set##F2();                                                                 \
0074   }                                                                            \
0075   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
0076 
0077 #define BOOL_BIT_3(FAMILY, ENUM, FIELD, F1, F2, F3)                            \
0078   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
0079   void set##FIELD() {                                                          \
0080     FAMILY.set(ENUM::FIELD);                                                   \
0081     set##F1();                                                                 \
0082     set##F2();                                                                 \
0083     set##F3();                                                                 \
0084   }                                                                            \
0085   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
0086 
0087 // Generate get, set and reset functions for 'properties'.
0088 #define PROPERTY(ENUM, FIELD) BOOL_BIT(Properties, ENUM, FIELD)
0089 #define PROPERTY_1(ENUM, FIELD, F1) BOOL_BIT_1(Properties, ENUM, FIELD, F1)
0090 #define PROPERTY_2(ENUM, FIELD, F1, F2)                                        \
0091   BOOL_BIT_2(Properties, ENUM, FIELD, F1, F2)
0092 #define PROPERTY_3(ENUM, FIELD, F1, F2, F3)                                    \
0093   BOOL_BIT_3(Properties, ENUM, FIELD, F1, F2, F3)
0094 
0095 // Generate get, set and reset functions for 'kinds'.
0096 #define KIND(ENUM, FIELD) BOOL_BIT(Kinds, ENUM, FIELD)
0097 #define KIND_1(ENUM, FIELD, F1) BOOL_BIT_1(Kinds, ENUM, FIELD, F1)
0098 #define KIND_2(ENUM, FIELD, F1, F2) BOOL_BIT_2(Kinds, ENUM, FIELD, F1, F2)
0099 #define KIND_3(ENUM, FIELD, F1, F2, F3)                                        \
0100   BOOL_BIT_3(Kinds, ENUM, FIELD, F1, F2, F3)
0101 
0102 const int HEX_WIDTH = 12;
0103 inline FormattedNumber hexValue(uint64_t N, unsigned Width = HEX_WIDTH,
0104                                 bool Upper = false) {
0105   return format_hex(N, Width, Upper);
0106 }
0107 
0108 // Output the hexadecimal representation of 'Value' using '[0x%08x]' format.
0109 inline std::string hexString(uint64_t Value, size_t Width = HEX_WIDTH) {
0110   std::string String;
0111   raw_string_ostream Stream(String);
0112   Stream << hexValue(Value, Width, false);
0113   return String;
0114 }
0115 
0116 // Get a hexadecimal string representation for the given value.
0117 inline std::string hexSquareString(uint64_t Value) {
0118   return (Twine("[") + Twine(hexString(Value)) + Twine("]")).str();
0119 }
0120 
0121 // Return a string with the First and Others separated by spaces.
0122 template <typename... Args>
0123 std::string formatAttributes(const StringRef First, Args... Others) {
0124   const auto List = {First, Others...};
0125   std::stringstream Stream;
0126   size_t Size = 0;
0127   for (const StringRef &Item : List) {
0128     Stream << (Size ? " " : "") << Item.str();
0129     Size = Item.size();
0130   }
0131   Stream << (Size ? " " : "");
0132   return Stream.str();
0133 }
0134 
0135 // Add an item to a map with second being a small vector.
0136 template <typename MapType, typename KeyType, typename ValueType>
0137 void addItem(MapType *Map, KeyType Key, ValueType Value) {
0138   (*Map)[Key].push_back(Value);
0139 }
0140 
0141 // Double map data structure.
0142 template <typename FirstKeyType, typename SecondKeyType, typename ValueType>
0143 class LVDoubleMap {
0144   static_assert(std::is_pointer<ValueType>::value,
0145                 "ValueType must be a pointer.");
0146   using LVSecondMapType = std::map<SecondKeyType, ValueType>;
0147   using LVFirstMapType =
0148       std::map<FirstKeyType, std::unique_ptr<LVSecondMapType>>;
0149   using LVAuxMapType = std::map<SecondKeyType, FirstKeyType>;
0150   using LVValueTypes = std::vector<ValueType>;
0151   LVFirstMapType FirstMap;
0152   LVAuxMapType AuxMap;
0153 
0154 public:
0155   void add(FirstKeyType FirstKey, SecondKeyType SecondKey, ValueType Value) {
0156     typename LVFirstMapType::iterator FirstIter = FirstMap.find(FirstKey);
0157     if (FirstIter == FirstMap.end()) {
0158       auto SecondMapSP = std::make_unique<LVSecondMapType>();
0159       SecondMapSP->emplace(SecondKey, Value);
0160       FirstMap.emplace(FirstKey, std::move(SecondMapSP));
0161     } else {
0162       LVSecondMapType *SecondMap = FirstIter->second.get();
0163       if (SecondMap->find(SecondKey) == SecondMap->end())
0164         SecondMap->emplace(SecondKey, Value);
0165     }
0166 
0167     typename LVAuxMapType::iterator AuxIter = AuxMap.find(SecondKey);
0168     if (AuxIter == AuxMap.end()) {
0169       AuxMap.emplace(SecondKey, FirstKey);
0170     }
0171   }
0172 
0173   LVSecondMapType *findMap(FirstKeyType FirstKey) const {
0174     typename LVFirstMapType::const_iterator FirstIter = FirstMap.find(FirstKey);
0175     if (FirstIter == FirstMap.end())
0176       return nullptr;
0177 
0178     return FirstIter->second.get();
0179   }
0180 
0181   ValueType find(FirstKeyType FirstKey, SecondKeyType SecondKey) const {
0182     LVSecondMapType *SecondMap = findMap(FirstKey);
0183     if (!SecondMap)
0184       return nullptr;
0185 
0186     typename LVSecondMapType::const_iterator SecondIter =
0187         SecondMap->find(SecondKey);
0188     return (SecondIter != SecondMap->end()) ? SecondIter->second : nullptr;
0189   }
0190 
0191   ValueType find(SecondKeyType SecondKey) const {
0192     typename LVAuxMapType::const_iterator AuxIter = AuxMap.find(SecondKey);
0193     if (AuxIter == AuxMap.end())
0194       return nullptr;
0195     return find(AuxIter->second, SecondKey);
0196   }
0197 
0198   // Return a vector with all the 'ValueType' values.
0199   LVValueTypes find() const {
0200     LVValueTypes Values;
0201     if (FirstMap.empty())
0202       return Values;
0203     for (typename LVFirstMapType::const_reference FirstEntry : FirstMap) {
0204       LVSecondMapType &SecondMap = *FirstEntry.second;
0205       for (typename LVSecondMapType::const_reference SecondEntry : SecondMap)
0206         Values.push_back(SecondEntry.second);
0207     }
0208     return Values;
0209   }
0210 };
0211 
0212 // Unified and flattened pathnames.
0213 std::string transformPath(StringRef Path);
0214 std::string flattenedFilePath(StringRef Path);
0215 
0216 inline std::string formattedKind(StringRef Kind) {
0217   return (Twine("{") + Twine(Kind) + Twine("}")).str();
0218 }
0219 
0220 inline std::string formattedName(StringRef Name) {
0221   return (Twine("'") + Twine(Name) + Twine("'")).str();
0222 }
0223 
0224 inline std::string formattedNames(StringRef Name1, StringRef Name2) {
0225   return (Twine("'") + Twine(Name1) + Twine(Name2) + Twine("'")).str();
0226 }
0227 
0228 // The given string represents a symbol or type name with optional enclosing
0229 // scopes, such as: name, name<..>, scope::name, scope::..::name, etc.
0230 // The string can have multiple references to template instantiations.
0231 // It returns the inner most component.
0232 LVLexicalComponent getInnerComponent(StringRef Name);
0233 LVStringRefs getAllLexicalComponents(StringRef Name);
0234 std::string getScopedName(const LVStringRefs &Components,
0235                           StringRef BaseName = {});
0236 
0237 // These are the values assigned to the debug location record IDs.
0238 // See DebugInfo/CodeView/CodeViewSymbols.def.
0239 // S_DEFRANGE                               0x113f
0240 // S_DEFRANGE_SUBFIELD                      0x1140
0241 // S_DEFRANGE_REGISTER                      0x1141
0242 // S_DEFRANGE_FRAMEPOINTER_REL              0x1142
0243 // S_DEFRANGE_SUBFIELD_REGISTER             0x1143
0244 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE   0x1144
0245 // S_DEFRANGE_REGISTER_REL                  0x1145
0246 // When recording CodeView debug location, the above values are truncated
0247 // to a uint8_t value in order to fit the 'OpCode' used for the logical
0248 // debug location operations.
0249 // Return the original CodeView enum value.
0250 inline uint16_t getCodeViewOperationCode(uint8_t Code) { return 0x1100 | Code; }
0251 
0252 } // end namespace logicalview
0253 } // end namespace llvm
0254 
0255 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H