xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/vp/cm_fc_ld/PatchInfoRecord.h (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
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