1 /* 2 * Copyright (c) 2019, Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 // PatchInfo record. 23 // 24 25 #pragma once 26 27 #ifndef __CM_FC_PATCHINFO_RECORD_H__ 28 #define __CM_FC_PATCHINFO_RECORD_H__ 29 30 #include <cstddef> 31 #include <cstring> 32 33 #include <algorithm> 34 #include <list> 35 #include <map> 36 #include <queue> 37 #include <string> 38 #include <tuple> 39 40 #include "PatchInfo.h" 41 #include "media_class_trace.h" 42 43 namespace cm { 44 45 namespace patch { 46 47 48 class Binary; 49 50 /// Symbol has @p Name and its definition by @p Bin and @p Addr within that 51 /// binary. A symbol may not has a binary associated. In that case, that's 52 /// an *unresolved* symbol. 53 /// 54 class Symbol { 55 const char *Name; ///< Name of the symbol. 56 unsigned Extra; ///< Extra info. 57 Binary *Bin; ///< Binary where the symbol is defined. 58 unsigned Addr; ///< Symbol's address within that binary. 59 60 public: Symbol(const char * N,unsigned E,Binary * B,unsigned A)61 Symbol(const char *N, unsigned E, Binary *B, unsigned A) 62 : Name(N), Extra(E), Bin(B), Addr(A) {} 63 isUnresolved()64 bool isUnresolved() const { return !Bin; } 65 getName()66 const char *getName() const { return Name; } setName(const char * N)67 void setName(const char *N) { Name = N; } 68 getExtra()69 unsigned getExtra() const { return Extra; } setExtra(unsigned E)70 void setExtra(unsigned E) { Extra = E; } 71 getBinary()72 Binary *getBinary() const { return Bin; } setBinary(Binary * B)73 void setBinary(Binary *B) { Bin = B; } 74 getAddr()75 unsigned getAddr() const { return Addr; } setAddr(unsigned A)76 void setAddr(unsigned A) { Addr = A; } 77 MEDIA_CLASS_DEFINE_END(cm__patch__Symbol) 78 }; 79 80 /// Relocation defines a location referencing a symbol. That location is 81 /// defined by @p Bin and @p Offset within that binary. @p Sym is the symbol it 82 /// refrenced. 83 /// 84 class Relocation { 85 unsigned Offset; ///< The offset in that binary where the relocation applies. 86 Symbol *Sym; ///< The symbol this relocation uses. 87 88 public: Relocation(unsigned Off,Symbol * S)89 Relocation(unsigned Off, Symbol *S) : Offset(Off), Sym(S) {} 90 getSymbol()91 Symbol *getSymbol() const { return Sym; } setSymbol(Symbol * S)92 void setSymbol(Symbol *S) { Sym = S; } 93 getOffset()94 unsigned getOffset() const { return Offset; } setOffset(unsigned Off)95 void setOffset(unsigned Off) { Offset = Off; } 96 MEDIA_CLASS_DEFINE_END(cm__patch__Relocation) 97 }; 98 99 100 class RegAccess { 101 unsigned Offset; 102 unsigned RegNo; 103 unsigned DefUseToken; 104 105 public: RegAccess(unsigned Off,unsigned R,unsigned DUT)106 RegAccess(unsigned Off, unsigned R, unsigned DUT) 107 : Offset(Off), RegNo(R), DefUseToken(DUT) {} 108 getOffset()109 unsigned getOffset() const { return Offset; } getRegNo()110 unsigned getRegNo() const { return RegNo; } getDUT()111 unsigned getDUT() const { return DefUseToken; } 112 getToken()113 std::pair<bool, unsigned> getToken() const { 114 unsigned T = DefUseToken & cm::patch::RDUT_TOKMASK; 115 bool HasToken = (T != RDUT_TOKMASK); 116 return std::make_pair(HasToken, T); 117 } 118 isDef()119 bool isDef() const { 120 return (DefUseToken & cm::patch::RDUT_DUMASK) == cm::patch::RDUT_FULLDEF; 121 } 122 isUse()123 bool isUse() const { 124 return (DefUseToken & cm::patch::RDUT_DUMASK) == cm::patch::RDUT_FULLUSE; 125 } 126 isDefByToken()127 bool isDefByToken() const { 128 bool HasToken; 129 std::tie(HasToken, std::ignore) = getToken(); 130 return HasToken && isDef(); 131 } 132 isUseByToken()133 bool isUseByToken() const { 134 bool HasToken; 135 std::tie(HasToken, std::ignore) = getToken(); 136 return HasToken && isUse(); 137 } 138 isDefNotByToken()139 bool isDefNotByToken() const { 140 bool HasToken; 141 std::tie(HasToken, std::ignore) = getToken(); 142 return !HasToken && isDef(); 143 } 144 isUseNotByToken()145 bool isUseNotByToken() const { 146 bool HasToken; 147 std::tie(HasToken, std::ignore) = getToken(); 148 return !HasToken && isUse(); 149 } 150 151 bool operator==(RegAccess &Other) const { 152 return Offset == Other.Offset && 153 RegNo == Other.RegNo && 154 DefUseToken == Other.DefUseToken; 155 } 156 MEDIA_CLASS_DEFINE_END(cm__patch__RegAccess) 157 }; 158 159 class Token { 160 unsigned TokenNo; 161 162 public: Token(unsigned T)163 Token(unsigned T) : TokenNo(T) {} 164 getTokenNo()165 unsigned getTokenNo() const { return TokenNo; } 166 MEDIA_CLASS_DEFINE_END(cm__patch__Token) 167 }; 168 169 class DepNode { 170 typedef std::list<RegAccess *> RegAccRefList; 171 typedef std::list<DepNode *> NodeRefList; 172 173 Binary *Bin; 174 unsigned Offset; 175 bool Barrier; 176 177 unsigned Distance; 178 unsigned RdTokenMask; 179 unsigned WrTokenMask; 180 181 RegAccRefList AccList; 182 183 // From node this node depends on. 184 NodeRefList FromList; 185 // To nodes which depends on this node. There are two kinds of such nodes: 186 // one depends on registers used by this node and 187 // the other depends on registers defined by this node. 188 NodeRefList ToList[2]; // 0 - from Use of this node; 189 // 1 - from Def of this node. 190 191 public: DepNode(Binary * B,unsigned Off,bool IsBarrier)192 DepNode(Binary *B, unsigned Off, bool IsBarrier) 193 : Bin(B), Offset(Off), Barrier(IsBarrier), Distance(0), 194 RdTokenMask(0), WrTokenMask(0) {} 195 getBinary()196 Binary *getBinary() const { return Bin; } getOffset()197 unsigned getOffset() const { return Offset; } isBarrier()198 bool isBarrier() const { return Barrier; } 199 clearAccList()200 void clearAccList() { AccList.clear(); } 201 appendRegAcc(RegAccess * Acc)202 void appendRegAcc(RegAccess *Acc) { 203 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 204 if (*(*AI) == *Acc) 205 return; 206 } 207 AccList.push_back(Acc); 208 } 209 addFromNode(DepNode * N)210 void addFromNode(DepNode *N) { FromList.push_back(N); } addToNode(DepNode * N,bool FromDef)211 void addToNode(DepNode *N, bool FromDef) { ToList[FromDef].push_back(N); } 212 clearFromNodes()213 void clearFromNodes() { FromList.clear(); } clearToNodes(bool FromDef)214 void clearToNodes(bool FromDef) { ToList[FromDef].clear(); } 215 from_empty()216 bool from_empty() const { return FromList.empty(); } to_empty(bool FromDef)217 bool to_empty(bool FromDef) const { return ToList[FromDef].empty(); } 218 acc_begin()219 RegAccRefList::iterator acc_begin() { return AccList.begin(); } acc_end()220 RegAccRefList::iterator acc_end() { return AccList.end(); } 221 from_begin()222 NodeRefList::iterator from_begin() { return FromList.begin(); } from_end()223 NodeRefList::iterator from_end() { return FromList.end(); } 224 to_begin(bool FromDef)225 NodeRefList::iterator to_begin(bool FromDef) { 226 return ToList[FromDef].begin(); 227 } to_end(bool FromDef)228 NodeRefList::iterator to_end(bool FromDef) { 229 return ToList[FromDef].end(); 230 } 231 getDistance()232 unsigned getDistance() const { return Distance; } setDistance(unsigned D)233 void setDistance(unsigned D) { Distance = D; } updateDistance(unsigned D)234 void updateDistance(unsigned D) { 235 if (Distance == 0) 236 Distance = D; 237 else 238 Distance = std::min(D, Distance); 239 } 240 getRdTokenMask()241 unsigned getRdTokenMask() const { return RdTokenMask; } getWrTokenMask()242 unsigned getWrTokenMask() const { return WrTokenMask; } setRdTokenMask(unsigned M)243 void setRdTokenMask(unsigned M) { RdTokenMask = M; } setWrTokenMask(unsigned M)244 void setWrTokenMask(unsigned M) { WrTokenMask = M; } mergeRdTokenMask(unsigned M)245 void mergeRdTokenMask(unsigned M) { RdTokenMask |= M; } mergeWrTokenMask(unsigned M)246 void mergeWrTokenMask(unsigned M) { WrTokenMask |= M; } 247 isDef(unsigned Reg)248 bool isDef(unsigned Reg) const { 249 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 250 RegAccess *Acc = *AI; 251 if (Acc->getRegNo() == Reg && Acc->isDef()) 252 return true; 253 } 254 return false; 255 } 256 isUse(unsigned Reg)257 bool isUse(unsigned Reg) const { 258 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 259 RegAccess *Acc = *AI; 260 if (Acc->getRegNo() == Reg && Acc->isUse()) 261 return true; 262 } 263 return false; 264 } 265 isDefOnly(unsigned Reg)266 bool isDefOnly(unsigned Reg) const { 267 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 268 RegAccess *Acc = *AI; 269 if (Acc->getRegNo() == Reg && !Acc->isDef()) 270 return false; 271 } 272 return true; 273 } 274 isUseOnly(unsigned Reg)275 bool isUseOnly(unsigned Reg) const { 276 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 277 RegAccess *Acc = *AI; 278 if (Acc->getRegNo() == Reg && !Acc->isUse()) 279 return false; 280 } 281 return true; 282 } 283 isDefByToken(unsigned Reg)284 bool isDefByToken(unsigned Reg) const { 285 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 286 RegAccess *Acc = *AI; 287 if (Acc->getRegNo() == Reg && Acc->isDefByToken()) 288 return true; 289 } 290 return false; 291 } 292 isUseByToken(unsigned Reg)293 bool isUseByToken(unsigned Reg) const { 294 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 295 RegAccess *Acc = *AI; 296 if (Acc->getRegNo() == Reg && Acc->isUseByToken()) 297 return true; 298 } 299 return false; 300 } 301 isDefNotByToken(unsigned Reg)302 bool isDefNotByToken(unsigned Reg) const { 303 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 304 RegAccess *Acc = *AI; 305 if (Acc->getRegNo() == Reg && !Acc->isDefNotByToken()) 306 return false; 307 } 308 return true; 309 } 310 isUseNotByToken(unsigned Reg)311 bool isUseNotByToken(unsigned Reg) const { 312 for (auto AI = AccList.begin(), AE = AccList.end(); AI != AE; ++AI) { 313 RegAccess *Acc = *AI; 314 if (Acc->getRegNo() == Reg && !Acc->isUseNotByToken()) 315 return false; 316 } 317 return true; 318 } 319 MEDIA_CLASS_DEFINE_END(cm__patch__DepNode) 320 }; 321 322 class DepEdge { 323 DepNode *Head; 324 DepNode *Tail; 325 bool HeadDef; 326 327 public: DepEdge(DepNode * H,DepNode * T,bool FromDef)328 DepEdge(DepNode *H, DepNode *T, bool FromDef) 329 : Head(H), Tail(T), HeadDef(FromDef) {} 330 getHead()331 DepNode *getHead() const { return Head; } getTail()332 DepNode *getTail() const { return Tail; } 333 isHeadDef()334 bool isHeadDef() const { return HeadDef; } 335 MEDIA_CLASS_DEFINE_END(cm__patch__DepEdge) 336 }; 337 338 339 /// Binary is a sequence of byte containing the machine code specified by @p 340 /// Data and @p Size. It has 0 or more reference to symbol and 0 or more 341 /// relocations. 342 /// 343 class Binary { 344 public: 345 typedef std::list<Relocation> RelList; 346 typedef std::list<RegAccess> RegAccList; 347 typedef std::list<Token> TokList; 348 349 struct DepNodeCompare { operatorDepNodeCompare350 bool operator()(DepNode *A, DepNode *B) { 351 return A->getOffset() < B->getOffset(); 352 } 353 }; 354 typedef std::list<DepNode *> SyncPointList; 355 356 private: 357 const char *Data; ///< The buffer containing the binary. 358 std::size_t Size; ///< The size of that binary. 359 unsigned LinkType; ///< The type of linkage, i.e., NONE, CALLER, or CALLEE. 360 361 RelList Rels; 362 RegAccList InitRegAcc; 363 RegAccList FiniRegAcc; 364 TokList Toks; 365 SyncPointList SyncPoints; 366 367 unsigned Order; 368 unsigned Position; 369 370 const Symbol *Name; 371 372 public: Binary(const char * B,std::size_t S)373 Binary(const char *B, std::size_t S) : 374 Data(B), Size(S), LinkType(0), Order(0), Position(unsigned(-1)), Name(nullptr) {} 375 rel_begin()376 RelList::const_iterator rel_begin() const { return Rels.begin(); } rel_end()377 RelList::const_iterator rel_end() const { return Rels.end(); } 378 rel_begin()379 RelList::iterator rel_begin() { return Rels.begin(); } rel_end()380 RelList::iterator rel_end() { return Rels.end(); } 381 addReloc(unsigned Off,Symbol * S)382 Relocation *addReloc(unsigned Off, Symbol *S) { 383 Rels.push_back(Relocation(Off, S)); 384 return &Rels.back(); 385 } 386 387 initreg_begin()388 RegAccList::const_iterator initreg_begin() const { 389 return InitRegAcc.begin(); 390 } initreg_end()391 RegAccList::const_iterator initreg_end() const { 392 return InitRegAcc.end(); 393 } 394 initreg_begin()395 RegAccList::iterator initreg_begin() { return InitRegAcc.begin(); } initreg_end()396 RegAccList::iterator initreg_end() { return InitRegAcc.end(); } 397 finireg_begin()398 RegAccList::const_iterator finireg_begin() const { 399 return FiniRegAcc.begin(); 400 } finireg_end()401 RegAccList::const_iterator finireg_end() const { 402 return FiniRegAcc.end(); 403 } 404 finireg_begin()405 RegAccList::iterator finireg_begin() { return FiniRegAcc.begin(); } finireg_end()406 RegAccList::iterator finireg_end() { return FiniRegAcc.end(); } 407 addInitRegAccess(unsigned Off,unsigned RegNo,unsigned DUT)408 RegAccess *addInitRegAccess(unsigned Off, unsigned RegNo, unsigned DUT) { 409 InitRegAcc.push_back(RegAccess(Off, RegNo, DUT)); 410 return &InitRegAcc.back(); 411 } 412 addFiniRegAccess(unsigned Off,unsigned RegNo,unsigned DUT)413 RegAccess *addFiniRegAccess(unsigned Off, unsigned RegNo, unsigned DUT) { 414 FiniRegAcc.push_back(RegAccess(Off, RegNo, DUT)); 415 return &FiniRegAcc.back(); 416 } 417 tok_begin()418 TokList::const_iterator tok_begin() const { return Toks.begin(); } tok_end()419 TokList::const_iterator tok_end() const { return Toks.end(); } 420 tok_begin()421 TokList::iterator tok_begin() { return Toks.begin(); } tok_end()422 TokList::iterator tok_end() { return Toks.end(); } 423 addToken(unsigned T)424 Token *addToken(unsigned T) { 425 Toks.push_back(Token(T)); 426 return &Toks.back(); 427 } 428 clearSyncPoints()429 void clearSyncPoints() { SyncPoints.clear(); } insertSyncPoint(DepNode * N)430 void insertSyncPoint(DepNode *N) { SyncPoints.push_back(N); } sortSyncPoints()431 void sortSyncPoints() { SyncPoints.sort(DepNodeCompare()); } 432 sp_begin()433 SyncPointList::const_iterator sp_begin() const { return SyncPoints.begin(); } sp_end()434 SyncPointList::const_iterator sp_end() const { return SyncPoints.end(); } sp_begin()435 SyncPointList::iterator sp_begin() { return SyncPoints.begin(); } sp_end()436 SyncPointList::iterator sp_end() { return SyncPoints.end(); } 437 438 getData()439 const char *getData() const { return Data; } setData(const char * Buf)440 void setData(const char *Buf) { Data = Buf; } 441 getSize()442 const std::size_t getSize() const { return Size; } setSize(std::size_t S)443 void setSize(std::size_t S) { Size = S; } 444 getLinkType()445 const unsigned getLinkType() const { return LinkType; } setLinkType(unsigned LT)446 void setLinkType(unsigned LT) { LinkType = LT; } 447 getOrder()448 const unsigned getOrder() const { return Order; } setOrder(unsigned O)449 void setOrder(unsigned O) { Order = O; } 450 getPos()451 const unsigned getPos() const { return Order; } setPos(unsigned O)452 void setPos(unsigned O) { Order = O; } 453 getName()454 const Symbol *getName() const { return Name; } setName(const Symbol * S)455 void setName(const Symbol *S) { Name = S; } 456 MEDIA_CLASS_DEFINE_END(cm__patch__Binary) 457 }; 458 459 /// Collection 460 class Collection { 461 public: 462 typedef std::list<Binary> BinaryList; 463 typedef std::list<Symbol> SymbolList; 464 465 struct cstring_less { operatorcstring_less466 bool operator()(const char *s0, const char *s1) const { 467 return std::strcmp(s0, s1) < 0; 468 } 469 }; 470 471 private: 472 BinaryList Binaries; 473 SymbolList Symbols; 474 475 unsigned Platform; 476 unsigned UniqueID; 477 478 std::list<std::string> NewNames; 479 480 std::map<const char *, Symbol *, cstring_less> SymbolMap; 481 482 std::string Linked; 483 484 public: Collection()485 Collection() : Platform(PP_NONE), UniqueID(0) {} 486 getPlatform()487 unsigned getPlatform() const { return Platform; } setPlatform(unsigned P)488 void setPlatform(unsigned P) { Platform = P; } 489 bin_begin()490 BinaryList::const_iterator bin_begin() const { return Binaries.begin(); } bin_end()491 BinaryList::const_iterator bin_end() const { return Binaries.end(); } 492 bin_begin()493 BinaryList::iterator bin_begin() { return Binaries.begin(); } bin_end()494 BinaryList::iterator bin_end() { return Binaries.end(); } 495 sym_begin()496 SymbolList::const_iterator sym_begin() const { return Symbols.begin(); } sym_end()497 SymbolList::const_iterator sym_end() const { return Symbols.end(); } 498 sym_begin()499 SymbolList::iterator sym_begin() { return Symbols.begin(); } sym_end()500 SymbolList::iterator sym_end() { return Symbols.end(); } 501 addBinary(const char * B,std::size_t S)502 Binary *addBinary(const char *B, std::size_t S) { 503 Binaries.push_back(Binary(B, S)); 504 return &Binaries.back(); 505 } 506 addSymbol(const char * Name)507 Symbol *addSymbol(const char *Name) { 508 auto I = SymbolMap.find(Name); 509 if (I != SymbolMap.end()) 510 return I->second; 511 Symbols.push_back(Symbol(Name, 0, nullptr, 0)); 512 Symbol *S = &Symbols.back(); 513 SymbolMap.insert(std::make_pair(Name, S)); 514 return S; 515 } 516 getSymbol(const char * Name)517 Symbol *getSymbol(const char *Name) { 518 auto I = SymbolMap.find(Name); 519 if (I != SymbolMap.end()) 520 return I->second; 521 return nullptr; 522 } 523 getUniqueName(const char * Name)524 const char *getUniqueName(const char *Name) { 525 std::string UniqueName(Name); 526 UniqueName += "!"; 527 UniqueName += std::to_string(UniqueID++); 528 NewNames.push_back(std::move(UniqueName)); 529 return NewNames.back().c_str(); 530 } 531 setLinkedBinary(std::string && L)532 void setLinkedBinary(std::string &&L) { Linked = L; } getLinkedBinary()533 const std::string &getLinkedBinary() const { return Linked; } 534 MEDIA_CLASS_DEFINE_END(cm__patch__Collection) 535 }; 536 537 } // End namespace patch 538 } // End namespace cm 539 540 #endif // __CM_FC_PATCHINFO_RECORD_H__ 541