1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #ifndef _METADATA_H_ 10 #define _METADATA_H_ 11 12 #include <optional> 13 #include <iostream> 14 15 namespace vISA 16 { 17 18 // 19 // A metadata is simply a collection of (<key>, <value>) pairs that may be attached to an IR object (BB, Inst, Declare, etc.) 20 // Metadata is completely optional; vISA optimizations and transformations are not obliged to preserve them, and dropping them should not affect correctness 21 // Metadata key is a string, and only one value is allowed per key for now. 22 // Metadata value is represented by an MDNode abstract class, each subclass provides the actual implementation of the metadata value 23 // Currently there are only two types of metadata: MDString and MDLocation. 24 // Metadata memory management is performed by IR_Builder through the various allocaeMD* methods. 25 // An MDNode may be shared among muitiple IR objects, it's the user's responsiblity to ensure correct ownership and sharing behaviors. 26 // Each object has its own unqiue metadata map, however. 27 // Currently only G4_INST supports metadata through the setMetaData/getMetadata interface. 28 // OPEN: use enum instead of string as metadata key. This would speed up lookup at the expense of some flexibility. 29 // OPEN: better management schemes for a MDNode's lifetime/ownership. 30 // 31 32 enum class MDType 33 { 34 String, 35 SrcLoc, 36 TokenLoc 37 }; 38 39 // forward declaration so that the asMD*() calls can work 40 class MDString; 41 class MDLocation; 42 class MDTokenLocation; 43 44 class MDNode 45 { 46 47 const MDType nodeType; 48 49 protected: MDNode(MDType ty)50 MDNode(MDType ty) : nodeType(ty) {} 51 52 public: 53 54 MDNode(const MDNode& node) = delete; 55 56 void operator=(const MDNode& node) = delete; 57 new(size_t sz,Mem_Manager & m)58 void* operator new(size_t sz, Mem_Manager& m) { return m.alloc(sz); } 59 ~MDNode()60 virtual ~MDNode() {} 61 isMDString()62 bool isMDString() const { return nodeType == MDType::String; } isMDLocation()63 bool isMDLocation() const { return nodeType == MDType::SrcLoc; } isMDTokenLocation()64 bool isMDTokenLocation() const { return nodeType == MDType::TokenLoc; } 65 asMDString()66 const MDString* asMDString() const 67 { 68 return isMDString() ? reinterpret_cast<const MDString*>(this) : nullptr; 69 } 70 asMDLocation()71 MDLocation* asMDLocation() const 72 { 73 return isMDLocation() ? reinterpret_cast<MDLocation*>(const_cast<MDNode*>(this)) : nullptr; 74 } 75 asMDTokenLocation()76 MDTokenLocation* asMDTokenLocation() const 77 { 78 return isMDTokenLocation() ? reinterpret_cast<MDTokenLocation*>(const_cast<MDNode*>(this)) : nullptr; 79 } 80 81 virtual void print(std::ostream& OS) const = 0; dump()82 void dump() const 83 { 84 print(std::cerr); 85 } 86 }; 87 88 class MDString : public MDNode 89 { 90 const std::string data; 91 92 public: 93 MDString(const std::string & str)94 MDString(const std::string& str) : MDNode(MDType::String), data(str) {} 95 96 MDString(const MDString& node) = delete; 97 98 void operator=(const MDString& node) = delete; 99 100 virtual ~MDString() = default; 101 getData()102 std::string getData() const { return data; } 103 print(std::ostream & OS)104 void print(std::ostream& OS) const 105 { 106 OS << "\"" << data << "\""; 107 } 108 }; 109 110 class MDLocation : public MDNode 111 { 112 int lineNo = -1; 113 const char* srcFilename = nullptr; 114 115 public: 116 MDLocation(int lineNo,const char * srcFilename)117 MDLocation(int lineNo, const char* srcFilename) : 118 MDNode(MDType::SrcLoc), lineNo(lineNo), srcFilename(srcFilename) {} 119 120 MDLocation(const MDLocation& node) = delete; 121 122 void operator=(const MDLocation& node) = delete; 123 124 ~MDLocation() = default; 125 new(size_t sz,Mem_Manager & m)126 void* operator new(size_t sz, Mem_Manager& m) { return m.alloc(sz); } getLineNo()127 int getLineNo() const { return lineNo; } getSrcFilename()128 const char* getSrcFilename() const { return srcFilename; } 129 print(std::ostream & OS)130 void print(std::ostream& OS) const 131 { 132 OS << "\"" << srcFilename << ":" << lineNo << "\""; 133 } 134 }; 135 136 class MDTokenLocation : public MDNode 137 { 138 std::vector<unsigned short> token; 139 std::vector<unsigned> global_id; 140 141 public: 142 MDTokenLocation(unsigned short _token,unsigned globalID)143 MDTokenLocation(unsigned short _token, unsigned globalID) : 144 MDNode(MDType::TokenLoc) 145 { 146 token.push_back(_token); 147 global_id.push_back(globalID); 148 } 149 150 MDTokenLocation(const MDTokenLocation& node) = delete; 151 152 void operator=(const MDTokenLocation& node) = delete; 153 154 ~MDTokenLocation() = default; 155 new(size_t sz,Mem_Manager & m)156 void* operator new(size_t sz, Mem_Manager& m) { return m.alloc(sz); } getTokenLocationNum()157 int getTokenLocationNum() const { return global_id.size(); } getToken(int i)158 unsigned short getToken(int i) const { return token[i]; } getTokenLocation(int i)159 unsigned getTokenLocation(int i) const { return global_id[i]; } addTokenLocation(unsigned short _token,int globalID)160 void addTokenLocation(unsigned short _token, int globalID) { token.push_back(_token), global_id.push_back(globalID); } 161 print(std::ostream & OS)162 void print(std::ostream& OS) const 163 { 164 OS << token.back() << "." << global_id.back(); 165 } 166 }; 167 168 class Metadata 169 { 170 171 std::unordered_map<std::string, MDNode*> MDMap; 172 173 public: Metadata()174 explicit Metadata() {} 175 176 Metadata(const Metadata& md) = delete; 177 ~Metadata()178 virtual ~Metadata() {} 179 new(size_t sz,Mem_Manager & m)180 void* operator new(size_t sz, Mem_Manager& m) { return m.alloc(sz); } 181 182 // it simply overwrites existing value for key if it already exists setMetadata(const std::string & key,MDNode * value)183 void setMetadata(const std::string& key, MDNode* value) 184 { 185 if (!value) 186 { 187 // do not allow nullptr value for now. ToDo: distinguish between nullptr value vs. metadata not set? 188 return; 189 } 190 MDMap[key] = value; 191 } 192 getMetadata(const std::string & key)193 MDNode* getMetadata(const std::string& key) 194 { 195 auto iter = MDMap.find(key); 196 return iter != MDMap.end() ? iter->second : nullptr; 197 } 198 isMetadataSet(const std::string & key)199 bool isMetadataSet(const std::string& key) 200 { 201 return MDMap.count(key); 202 } 203 print(std::ostream & OS)204 void print(std::ostream& OS) const 205 { 206 for (auto&& iter : MDMap) 207 { 208 OS << "\"" << iter.first << "\" : "; 209 iter.second->print(OS); 210 OS << "\n"; 211 } 212 } 213 dump()214 void dump() const 215 { 216 print(std::cerr); 217 } 218 219 // list the known keys here to avoid typos 220 inline static const std::string InstComment = "comment"; 221 inline static const std::string InstLoc = "location"; 222 inline static const std::string TokenLoc = "tokenlocation"; 223 }; 224 225 } 226 227 #endif 228