mlir.js 1.1 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816
  1. // Experimental
  2. import * as base from './base.js';
  3. import * as text from './text.js';
  4. const mlir = {};
  5. const _ = {};
  6. mlir.ModelFactory = class {
  7. async match(context) {
  8. const stream = context.stream;
  9. const identifier = context.identifier;
  10. const extension = identifier.split('.').pop().toLowerCase();
  11. if (stream && stream.length > 4) {
  12. const buffer = stream.peek(4);
  13. const signature = String.fromCharCode.apply(null, buffer);
  14. if (signature === 'ML\xEFR') {
  15. return context.set('mlir.binary');
  16. }
  17. }
  18. try {
  19. const reader = await context.read('text', 0x10000);
  20. let whitespace = true;
  21. for (let line = reader.read('\n'); line !== undefined; line = reader.read('\n')) {
  22. if (/module\s+(@\w+|\w+|attributes|\{)/.test(line) ||
  23. /tensor<[\w\d]+>/.test(line) ||
  24. /func[.\s]*@\w+/.test(line) ||
  25. /%\w+\s*=\s*"[\w.]+/.test(line) ||
  26. /%\w+\s*=\s*\w+\./.test(line) ||
  27. /!\w+\s*=\s*![\w.]+</.test(line) ||
  28. /#\w+\s*=\s*#[\w.]+</.test(line) ||
  29. /#\w+\s*=\s*loc\s*\(/.test(line) ||
  30. /\w+\.\w+(?:\s+\w+)*\s+@\w+/.test(line) ||
  31. /\w+\.\w+\s+#[\w.]+</.test(line) ||
  32. /\w+\.\w+\s*<?\{/.test(line) ||
  33. /:\s*![\w.]+/.test(line) ||
  34. /(%\w+|\w{2,}|[)])\s*:\s*(\[|tensor<)/.test(line) ||
  35. /->\s*(![\w.]+|\(|tensor<)/.test(line)) {
  36. return context.set('mlir.text');
  37. }
  38. if (line && !line.trim().startsWith('//')) {
  39. whitespace = false;
  40. }
  41. }
  42. if (extension === 'mlir' && whitespace) {
  43. return context.set('mlir.text');
  44. }
  45. } catch {
  46. // continue
  47. }
  48. return null;
  49. }
  50. async open(context) {
  51. const metadata = await mlir.Metadata.open(context);
  52. switch (context.type) {
  53. case 'mlir.text': {
  54. const decoder = await context.read('text.decoder');
  55. const config = new _.ParserConfig(new _.DialectContext(metadata));
  56. const state = new _.ParserState(decoder, config);
  57. const parser = new _.TopLevelOperationParser(state);
  58. const block = new _.Block();
  59. parser.parse(block);
  60. const model = new mlir.Model(config, 'MLIR', '', block, state.attributeAliasDefinitions);
  61. return model;
  62. }
  63. case 'mlir.binary': {
  64. const binary = await context.read('binary');
  65. const config = new _.ParserConfig(new _.DialectContext(metadata));
  66. const reader = new _.BytecodeReader(binary, config);
  67. const block = reader.read();
  68. const format = `MLIR Bytecode v${reader.version}`;
  69. const producer = reader.producer;
  70. const model = new mlir.Model(config, format, producer, block, new Map());
  71. return model;
  72. }
  73. default: {
  74. throw new mlir.Error(`Unsupported MLIR format '${context.type}'.`);
  75. }
  76. }
  77. }
  78. };
  79. mlir.Model = class {
  80. constructor(config, format, producer, block, attributeAliasDefinitions) {
  81. this.format = format;
  82. this.producer = producer || '';
  83. this.modules = [];
  84. this.functions = [];
  85. this.metadata = [];
  86. const modules = [];
  87. const isFunc = (name) => name.endsWith('.func') || /\.func_v\d+$/.test(name);
  88. const isModule = (name) => name.endsWith('.module');
  89. const collectModules = (operations, path, attributes) => {
  90. let identifier = 0;
  91. const funcs = [];
  92. const ops = [];
  93. for (const op of operations) {
  94. if (isFunc(op.name.getStringRef())) {
  95. funcs.push(op);
  96. } else if (isModule(op.name.getStringRef())) {
  97. let name = op.getAttr('sym_name');
  98. name = name ? name.value : `$${identifier++}`;
  99. const modulePath = [...path, name];
  100. for (const region of op.regions || []) {
  101. for (const blk of region.blocks || []) {
  102. collectModules(blk.operations || [], modulePath, op.getAttrDictionary());
  103. }
  104. }
  105. } else {
  106. ops.push(op);
  107. }
  108. }
  109. if (funcs.length > 0 || ops.length > 0) {
  110. let name = null;
  111. if (attributes.get('sym_name')) {
  112. name = attributes.get('sym_name');
  113. name = `@${name.value}`;
  114. }
  115. modules.push({ path, symName: name, funcs, ops, attributes });
  116. }
  117. };
  118. collectModules(block.operations, [], new Map());
  119. const formatPrefix = (path, symName) => {
  120. if (symName) {
  121. return symName;
  122. }
  123. if (modules.length !== 1 && path.length > 0) {
  124. return path.map((path) => `${path}`).join('::');
  125. }
  126. return '';
  127. };
  128. const functions = new Map();
  129. let identifier = 0;
  130. for (const module of modules) {
  131. const prefix = formatPrefix(module.path, module.symName);
  132. for (const func of module.funcs) {
  133. const sym_name = func.getAttr('sym_name');
  134. const base = sym_name ? sym_name.value : `$${identifier}`;
  135. identifier++;
  136. const name = prefix ? `${prefix}::@${base}` : `@${base}`;
  137. functions.set(name, { func, prefix, base, module });
  138. }
  139. }
  140. const context = new mlir.Context(functions);
  141. for (const [name, info] of functions) {
  142. const graph = context.graph(info.func, name);
  143. this.functions.push(graph);
  144. }
  145. for (const module of modules) {
  146. if (module.ops.length > 0 || module.attributes.size > 0) {
  147. const name = formatPrefix(module.path, module.symName) || '';
  148. const opName = _.RegisteredOperationName.lookup('builtin.module', config.context);
  149. const state = new _.OperationState(null, opName);
  150. state.attributes = module.attributes;
  151. state.regions = [{ blocks: [{ operations: module.ops, arguments: [] }] }];
  152. const op = _.Operation.create(state);
  153. const graph = context.graph(op, name);
  154. this.modules.push(graph);
  155. }
  156. }
  157. for (const [name, attribute] of attributeAliasDefinitions) {
  158. let value = attribute.type;
  159. if (!value) {
  160. value = typeof attribute.value === 'string' ? attribute.value : JSON.stringify(attribute.value);
  161. }
  162. const metadata = new mlir.Argument(name, value, 'attribute');
  163. this.metadata.push(metadata);
  164. }
  165. }
  166. };
  167. mlir.Graph = class {
  168. constructor(func, context, name) {
  169. this.name = name || '';
  170. if (!name && func.attributes.has('sym_name')) {
  171. const sym_name = func.attributes.get('sym_name');
  172. this.name = sym_name.value;
  173. }
  174. this.type = 'graph';
  175. if (func.name === 'func' || func.name.getStringRef().endsWith('.func') || /\.func_v\d+$/.test(func.name.getStringRef())) {
  176. this.type = 'function';
  177. }
  178. this.inputs = [];
  179. this.outputs = [];
  180. this.nodes = [];
  181. this.metadata = [];
  182. const tensors = new Map();
  183. if (func.attributes.has('function_type')) {
  184. const function_type = func.attributes.get('function_type');
  185. const args = func.regions && func.regions[0] && func.regions[0].blocks && func.regions[0].blocks[0] && func.regions[0].blocks[0].arguments ? func.regions[0].blocks[0].arguments : [];
  186. const inputs = function_type.type.inputs;
  187. const results = function_type.type.results;
  188. for (let i = 0; i < inputs.length; i++) {
  189. const input = inputs[i];
  190. const name = args[i] && args[i].name ? args[i].name : `%arg${i}`;
  191. const type = mlir.Utility.valueType(input.type || input);
  192. const value = new mlir.Value(name, type, '', null);
  193. const argument = new mlir.Argument(name, [value]);
  194. this.inputs.push(argument);
  195. }
  196. for (let i = 0; i < results.length; i++) {
  197. const output = results[i];
  198. const name = output.value || i.toString();
  199. const type = mlir.Utility.valueType(output.type);
  200. const valueName = output.value || output.name || `%result${i}`;
  201. const value = new mlir.Value(valueName, type, '', null);
  202. const argument = new mlir.Argument(name, [value]);
  203. this.outputs.push(argument);
  204. }
  205. }
  206. const values = new Map();
  207. values.map = (name) => {
  208. if (!values.has(name)) {
  209. values.set(name, { name, to: [], from: [] });
  210. }
  211. return values.get(name);
  212. };
  213. const operations = [];
  214. for (const region of func.regions) {
  215. for (const block of region.blocks) {
  216. for (const op of block.operations) {
  217. const operation = {
  218. identifier: op.identifier,
  219. name: op.name,
  220. label: op.label,
  221. attributes: op.getAttrDictionary(),
  222. operands: [],
  223. results: [],
  224. inputs: [],
  225. outputs: [],
  226. regions: op.regions,
  227. delete: false,
  228. };
  229. const opMetadata = op.name.metadata;
  230. const operands = op.operands;
  231. let lastVariadicIndex = -1;
  232. let lastVariadicName = null;
  233. if (opMetadata && opMetadata.operands) {
  234. for (let j = opMetadata.operands.length - 1; j >= 0; j--) {
  235. const metaOp = opMetadata.operands[j];
  236. if (metaOp.type && metaOp.type.name === 'Variadic') {
  237. lastVariadicIndex = j;
  238. lastVariadicName = metaOp.name;
  239. break;
  240. }
  241. }
  242. }
  243. for (let i = 0; i < operands.length; i++) {
  244. const input = op.operands[i];
  245. let inputName = null;
  246. const isVariadicOverflow = lastVariadicIndex >= 0 && i >= lastVariadicIndex;
  247. if (opMetadata && opMetadata.operands && opMetadata.operands[i]) {
  248. inputName = opMetadata.operands[i].name;
  249. } else if (isVariadicOverflow) {
  250. inputName = lastVariadicName;
  251. } else {
  252. inputName = input.name || i.toString();
  253. }
  254. if (typeof input.name !== 'string' || !input.name) {
  255. throw new mlir.Error(`Invalid operand name '${JSON.stringify(input.name)}'.`);
  256. }
  257. const value = values.map(input.name);
  258. value.to.push(operation);
  259. const arg = { name: input.name, type: input.type };
  260. operation.operands.push(arg);
  261. if (isVariadicOverflow && operation.inputs.length > 0 && operation.inputs[operation.inputs.length - 1].name === inputName) {
  262. operation.inputs[operation.inputs.length - 1].value.push(arg);
  263. } else {
  264. operation.inputs.push({ name: inputName, value: [arg] });
  265. }
  266. }
  267. const results = op.results;
  268. let lastVariadicResultIndex = -1;
  269. let lastVariadicResultName = null;
  270. if (opMetadata && opMetadata.results) {
  271. for (let j = opMetadata.results.length - 1; j >= 0; j--) {
  272. const metaRes = opMetadata.results[j];
  273. if (metaRes.type && metaRes.type.name === 'Variadic') {
  274. lastVariadicResultIndex = j;
  275. lastVariadicResultName = metaRes.name;
  276. break;
  277. }
  278. }
  279. }
  280. for (let i = 0; i < results.length; i++) {
  281. const output = results[i];
  282. if (!output.name) {
  283. continue;
  284. }
  285. const value = values.map(output.name);
  286. value.type = mlir.Utility.valueType(output.type);
  287. value.from.push(operation);
  288. let outputName = null;
  289. const isVariadicOverflow = lastVariadicResultIndex >= 0 && i >= lastVariadicResultIndex;
  290. if (opMetadata && opMetadata.results && opMetadata.results[i]) {
  291. outputName = opMetadata.results[i].name;
  292. } else if (isVariadicOverflow) {
  293. outputName = lastVariadicResultName;
  294. } else {
  295. outputName = output.name;
  296. }
  297. operation.results.push(value);
  298. if (isVariadicOverflow && operation.outputs.length > 0 && operation.outputs[operation.outputs.length - 1].name === outputName) {
  299. operation.outputs[operation.outputs.length - 1].value.push(value);
  300. } else {
  301. operation.outputs.push({
  302. name: outputName,
  303. value: [value]
  304. });
  305. }
  306. }
  307. operations.push(operation);
  308. }
  309. }
  310. }
  311. const constantMap = new Map();
  312. const constantTypes = new Set([
  313. 'tosa.const', 'stablehlo.constant', 'arith.constant',
  314. 'mhlo.constant', 'torch.constant.tensor', 'onnx.Constant'
  315. ]);
  316. for (const op of operations) {
  317. if (constantTypes.has(op.name.getStringRef()) &&
  318. op.operands.length === 0 &&
  319. op.attributes.size === 1 &&
  320. op.results.length === 1) {
  321. const result = op.results[0];
  322. if (result.to && result.to.length === 1) {
  323. if (result.to[0].name.getStringRef().endsWith('.return')) {
  324. continue;
  325. }
  326. const valueAttr = op.attributes.get('value') || op.attributes.get('values');
  327. if ((valueAttr instanceof _.DenseElementsAttr || valueAttr instanceof _.DenseResourceElementsAttr) && valueAttr.value !== null && valueAttr.type && valueAttr.type.toString().startsWith('tensor<')) {
  328. const type = mlir.Utility.valueType(valueAttr.type);
  329. if (type instanceof mlir.TensorType) {
  330. constantMap.set(result.name, new mlir.Tensor(type, valueAttr.value));
  331. op.delete = true;
  332. }
  333. }
  334. }
  335. }
  336. }
  337. const torchConstantMap = new Map();
  338. for (const op of operations) {
  339. const opName = op.name.getStringRef();
  340. if (opName === 'torch.constant.int' ||
  341. opName === 'torch.constant.bool' ||
  342. opName === 'torch.constant.float' ||
  343. opName === 'torch.constant.str' ||
  344. opName === 'torch.constant.none') {
  345. if (op.operands.length === 0 &&
  346. op.results.length === 1) {
  347. const result = op.results[0];
  348. if (result.to && result.to.length === 1) {
  349. let value = null;
  350. let type = null;
  351. const attr = op.attributes.get('value');
  352. const attrValue = attr && typeof attr === 'object' ? attr.value : attr;
  353. if (opName === 'torch.constant.int') {
  354. value = attrValue === undefined ? 0 : attrValue;
  355. type = 'int64';
  356. } else if (opName === 'torch.constant.bool') {
  357. value = attrValue === undefined ? false : attrValue;
  358. type = 'boolean';
  359. } else if (opName === 'torch.constant.float') {
  360. value = attrValue === undefined ? 0.0 : attrValue;
  361. type = 'float64';
  362. } else if (opName === 'torch.constant.str') {
  363. value = attrValue === undefined ? '' : attrValue;
  364. type = 'string';
  365. } else if (opName === 'torch.constant.none') {
  366. value = null;
  367. type = 'none';
  368. }
  369. torchConstantMap.set(result.name, { value, type });
  370. op.delete = true;
  371. }
  372. }
  373. }
  374. }
  375. for (const op of operations) {
  376. if (op.name === 'torch.prim.ListConstruct' &&
  377. op.results.length === 1) {
  378. const result = op.results[0];
  379. if (result.to && result.to.length === 1) {
  380. const inputValues = [];
  381. let allConstant = true;
  382. for (const operand of op.operands) {
  383. if (torchConstantMap.has(operand.name)) {
  384. inputValues.push(torchConstantMap.get(operand.name).value);
  385. } else {
  386. allConstant = false;
  387. break;
  388. }
  389. }
  390. if (allConstant) {
  391. torchConstantMap.set(result.name, { value: inputValues, type: 'list' });
  392. op.delete = true;
  393. }
  394. }
  395. }
  396. }
  397. const tensor = (arg) => {
  398. if (!tensors.has(arg.name)) {
  399. const initializer = constantMap.get(arg.name) || null;
  400. let type = null;
  401. if (arg.type instanceof mlir.TensorType) {
  402. type = arg.type;
  403. } else if (arg.type) {
  404. type = mlir.Utility.valueType(arg.type);
  405. }
  406. tensors.set(arg.name, new mlir.Value(arg.name, type, null, initializer));
  407. }
  408. return tensors.get(arg.name);
  409. };
  410. for (const input of this.inputs) {
  411. for (const arg of input.value) {
  412. if (!tensors.has(arg.name)) {
  413. tensors.set(arg.name, arg);
  414. }
  415. }
  416. }
  417. const returnOp = operations.find((op) => op.name.getStringRef().endsWith('.return'));
  418. if (returnOp) {
  419. for (let i = 0; i < this.outputs.length && i < returnOp.operands.length; i++) {
  420. const returnValue = returnOp.operands[i];
  421. if (returnValue && typeof returnValue.name === 'string' && returnValue.name.startsWith('%')) {
  422. const output = this.outputs[i];
  423. const returnType = mlir.Utility.valueType(returnValue.type);
  424. const initializer = constantMap.get(returnValue.name) || null;
  425. output.value[0] = new mlir.Value(returnValue.name, returnType, '', initializer);
  426. }
  427. }
  428. returnOp.delete = true;
  429. }
  430. for (const output of this.outputs) {
  431. for (let i = 0; i < output.value.length; i++) {
  432. const arg = output.value[i];
  433. if (tensors.has(arg.name)) {
  434. output.value[i] = tensors.get(arg.name);
  435. } else {
  436. tensors.set(arg.name, arg);
  437. }
  438. }
  439. }
  440. for (const op of operations.filter((op) => !op.delete)) {
  441. const node = new mlir.Node(op, context, tensor, torchConstantMap);
  442. this.nodes.push(node);
  443. }
  444. for (const [name, value] of func.attributes) {
  445. if (name === 'sym_name' || name === 'function_type') {
  446. continue;
  447. }
  448. const metadata = new mlir.Argument(name, value, 'attribute');
  449. this.metadata.push(metadata);
  450. }
  451. }
  452. };
  453. mlir.Argument = class {
  454. constructor(name, value, type = null) {
  455. this.name = name;
  456. this.value = value;
  457. this.type = type;
  458. if (this.type) {
  459. const typeStr = this.type instanceof _.Type ? this.type.toString() : this.type;
  460. switch (typeStr) {
  461. case 'i64': case 'si64': this.type = 'int64'; break;
  462. case 'i48': case 'si48': this.type = 'int48'; break;
  463. case 'i32': case 'si32': this.type = 'int32'; break;
  464. case 'i16': case 'si16': this.type = 'int16'; break;
  465. case 'i8': case 'si8': this.type = 'int8'; break;
  466. case 'i1': this.type = 'int1'; break;
  467. case 'f32': case 'float32': this.type = 'float32'; break;
  468. case 'f64': case 'float64': this.type = 'float64'; break;
  469. case 'f16': this.type = 'float16'; break;
  470. case 'f80': this.type = 'float80'; break;
  471. case 'f128': this.type = 'float128'; break;
  472. case null:
  473. case 'attribute':
  474. case 'boolean':
  475. case 'string':
  476. case 'int64':
  477. case 'int32':
  478. case 'int16':
  479. case 'int8':
  480. case 'float16':
  481. case 'tensor':
  482. case 'type':
  483. case 'dense':
  484. case 'function':
  485. case 'symbol':
  486. case 'graph':
  487. case 'list':
  488. case 'none':
  489. break;
  490. default:
  491. if (/^[usi]i?[0-9]+$/.test(typeStr) || /^f[0-9]+$/.test(typeStr) ||
  492. /^f\d+E\d+M\d+/.test(typeStr) ||
  493. typeStr === 'bf16' || typeStr === 'tf32' || typeStr === 'index' || typeStr === 'none' ||
  494. typeStr === 'unit' || typeStr.startsWith('!') || typeStr.startsWith('tensor<') ||
  495. typeStr.startsWith('memref<') || typeStr.startsWith('vector<')) {
  496. this.type = typeStr;
  497. break;
  498. }
  499. throw new mlir.Error(`Unsupported argument type '${typeStr}'.`);
  500. }
  501. }
  502. }
  503. };
  504. mlir.Value = class {
  505. constructor(name, type, description, initializer) {
  506. if (typeof name !== 'string') {
  507. throw new mlir.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);
  508. }
  509. this.name = name;
  510. this.type = !type && initializer ? initializer.type : type;
  511. this.description = description || null;
  512. this.initializer = initializer || null;
  513. }
  514. };
  515. mlir.Node = class {
  516. constructor(op, context, tensor, torchConstantMap) {
  517. if (!op.name) {
  518. throw new mlir.Error('Undefined node type.');
  519. }
  520. this.name = '';
  521. this.type = { ...op.name.getRegisteredInfo()?.metadata };
  522. this.type.name = op.label || op.identifier || '';
  523. this.type.identifier = op.name.getStringRef() || '';
  524. this.inputs = [];
  525. this.outputs = [];
  526. this.attributes = [];
  527. this.blocks = [];
  528. torchConstantMap = torchConstantMap || new Map();
  529. const segmentSizes = op.attributes && op.attributes.get('operandSegmentSizes');
  530. const operandMeta = this.type && this.type.operands;
  531. const operands = op.inputs || [];
  532. if (segmentSizes && operandMeta && Array.isArray(segmentSizes) && segmentSizes.length === operandMeta.length) {
  533. let offset = 0;
  534. for (let i = 0; i < segmentSizes.length; i++) {
  535. const size = segmentSizes[i];
  536. const name = operandMeta[i].name;
  537. for (let j = 0; j < size; j++) {
  538. if (offset + j < operands.length) {
  539. operands[offset + j] = { ...operands[offset + j], name };
  540. }
  541. }
  542. offset += size;
  543. }
  544. }
  545. const operandGroups = new Map();
  546. const operandOrder = [];
  547. for (const input of operands) {
  548. if (!operandGroups.has(input.name)) {
  549. operandGroups.set(input.name, []);
  550. operandOrder.push(input.name);
  551. }
  552. operandGroups.get(input.name).push(input);
  553. }
  554. for (const name of operandOrder) {
  555. const inputs = operandGroups.get(name);
  556. let argument = null;
  557. if (inputs.length === 1) {
  558. const [input] = inputs;
  559. if (Array.isArray(input.value) && input.value.length === 1) {
  560. const val = input.value[0];
  561. if (val && typeof val.name === 'string' && torchConstantMap.has(val.name)) {
  562. const constant = torchConstantMap.get(val.name);
  563. argument = new mlir.Argument(input.name, constant.value, constant.type);
  564. this.inputs.push(argument);
  565. continue;
  566. }
  567. }
  568. if (input.type) {
  569. const typeStr = input.type instanceof _.Type ? input.type.toString() : input.type;
  570. if (typeStr.startsWith('tensor<')) {
  571. const type = mlir.Utility.valueType(typeStr);
  572. const value = new mlir.Tensor(type, input.value);
  573. argument = new mlir.Argument(input.name, value, 'tensor');
  574. } else {
  575. argument = new mlir.Argument(input.name, input.value, input.type);
  576. }
  577. } else if (Array.isArray(input.value) && !input.value.every((value) => typeof value.name === 'string' && value.name.startsWith('%'))) {
  578. argument = new mlir.Argument(input.name, input.value, input.type || 'attribute');
  579. } else if (Array.isArray(input.value)) {
  580. argument = new mlir.Argument(input.name, input.value.map((arg) => tensor(arg)));
  581. } else {
  582. argument = new mlir.Argument(input.name, input.value, input.type || 'attribute');
  583. }
  584. } else {
  585. let allConstants = true;
  586. const constantValues = [];
  587. for (const input of inputs) {
  588. if (Array.isArray(input.value)) {
  589. for (const arg of input.value) {
  590. if (arg && typeof arg.name === 'string' && torchConstantMap.has(arg.name)) {
  591. constantValues.push(torchConstantMap.get(arg.name).value);
  592. } else {
  593. allConstants = false;
  594. break;
  595. }
  596. }
  597. } else {
  598. allConstants = false;
  599. }
  600. if (!allConstants) {
  601. break;
  602. }
  603. }
  604. if (allConstants && constantValues.length > 0) {
  605. argument = new mlir.Argument(name, constantValues, 'list');
  606. } else {
  607. const values = [];
  608. for (const input of inputs) {
  609. if (Array.isArray(input.value)) {
  610. values.push(...input.value.map((arg) => tensor(arg)));
  611. } else {
  612. values.push(tensor({ name: input.value, type: input.type }));
  613. }
  614. }
  615. argument = new mlir.Argument(name, values);
  616. }
  617. }
  618. this.inputs.push(argument);
  619. }
  620. for (const output of op.outputs || []) {
  621. const argument = new mlir.Argument(output.name, output.value.map((arg) => tensor(arg)));
  622. this.outputs.push(argument);
  623. }
  624. if (op.attributes) {
  625. for (const [name, attr] of op.attributes) {
  626. let value = attr;
  627. let type = null;
  628. if (attr instanceof _.SymbolRefAttr && context) {
  629. const graph = context.function(`${value.value}`);
  630. if (graph) {
  631. value = graph;
  632. type = 'function';
  633. }
  634. } else if (attr instanceof _.DenseElementsAttr) {
  635. value = new mlir.Tensor(mlir.Utility.valueType(attr.type), attr.value);
  636. type = 'tensor';
  637. } else if (attr instanceof _.DenseResourceElementsAttr) {
  638. value = new mlir.Tensor(mlir.Utility.valueType(attr.type), attr.value);
  639. type = 'tensor';
  640. } else if (attr instanceof _.SparseElementsAttr) {
  641. value = new mlir.Tensor(mlir.Utility.valueType(attr.type), attr.values);
  642. type = 'tensor';
  643. } else if (attr instanceof _.DenseArrayAttr) {
  644. value = attr.value;
  645. } else if (Array.isArray(attr)) {
  646. value = attr;
  647. } else if (attr) {
  648. value = attr.toString();
  649. }
  650. const attribute = new mlir.Argument(name, value, type || 'attribute');
  651. this.attributes.push(attribute);
  652. }
  653. }
  654. if (op.regions && op.regions.length > 0) {
  655. const opMetadata = this.type;
  656. for (let i = 0; i < op.regions.length; i++) {
  657. const region = op.regions[i];
  658. if (region.blocks && region.blocks.length > 0) {
  659. const name = (opMetadata.regions && opMetadata.regions[i] ? opMetadata.regions[i].name : null) || i.toString();
  660. const blockName = region.blocks[0].name || '';
  661. const func = { name: 'func', attributes: new Map(), regions: [region] };
  662. const graph = new mlir.Graph(func, context, blockName);
  663. const argument = new mlir.Argument(name, graph, 'graph');
  664. this.blocks.push(argument);
  665. }
  666. }
  667. }
  668. }
  669. };
  670. mlir.Tensor = class {
  671. constructor(type, data) {
  672. this.type = type;
  673. this.values = data;
  674. this.encoding = data instanceof Uint8Array ? '<' : '|';
  675. }
  676. };
  677. mlir.TensorType = class {
  678. constructor(dataType, shape) {
  679. this.dataType = mlir.Utility.dataType(dataType); // string
  680. this.shape = shape || new mlir.TensorShape([]); // mlir.TensorShape
  681. }
  682. toString() {
  683. return this.dataType + this.shape.toString();
  684. }
  685. };
  686. mlir.TensorShape = class {
  687. constructor(dimensions) {
  688. this.dimensions = dimensions;
  689. }
  690. toString() {
  691. if (!this.dimensions || this.dimensions.length === 0) {
  692. return '';
  693. }
  694. return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;
  695. }
  696. };
  697. mlir.Context = class {
  698. constructor(functions) {
  699. this._functions = functions; // Map of fullName -> {func, prefix, base, module}
  700. this._graphs = new Map();
  701. this._constructing = new Set();
  702. }
  703. graph(module, name) {
  704. if (!this._graphs.has(name)) {
  705. this._constructing.add(name);
  706. const graph = new mlir.Graph(module, this, name);
  707. this._graphs.set(name, graph);
  708. this._constructing.delete(name);
  709. }
  710. return this._graphs.get(name);
  711. }
  712. function(name) {
  713. if (this._graphs.has(name)) {
  714. return this._graphs.get(name);
  715. }
  716. if (this._constructing.has(name)) {
  717. return { name, type: 'function', nodes: [], inputs: [], outputs: [] };
  718. }
  719. if (this._functions.has(name)) {
  720. const info = this._functions.get(name);
  721. return this.graph(info.func, name);
  722. }
  723. for (const [fullName, info] of this._functions) {
  724. if (info.base === name) {
  725. if (this._graphs.has(fullName)) {
  726. return this._graphs.get(fullName);
  727. }
  728. if (this._constructing.has(fullName)) {
  729. return { name: fullName, type: 'function', nodes: [], inputs: [], outputs: [] };
  730. }
  731. return this.graph(info.func, fullName);
  732. }
  733. }
  734. return null;
  735. }
  736. };
  737. mlir.Utility = class {
  738. static dataType(value) {
  739. if (value instanceof _.ComplexType) {
  740. const elementType = mlir.Utility.dataType(value.elementType);
  741. return `complex<${elementType}>`;
  742. }
  743. if (value instanceof _.Type) {
  744. value = value.toString();
  745. }
  746. switch (value) {
  747. case 'index': return 'int64';
  748. case 'f16': return 'float16';
  749. case 'f32': return 'float32';
  750. case 'f64': return 'float64';
  751. case 'f80': return 'float80';
  752. case 'f128': return 'float128';
  753. case 'bf16': return 'bfloat16';
  754. case 'fp8': return 'float8';
  755. case 'fp8e4m3': return 'float8e4m3';
  756. case 'fp8_e4m3': return 'float8e4m3';
  757. case 'fp8e4m3fn': return 'float8e4m3fn';
  758. case 'fp8e5m2': return 'float8e5m2';
  759. case 'fp8_e5m2': return 'float8e5m2';
  760. case 'f4E2M1FN': return 'float4e2m1fn';
  761. case 'f6E2M3FN': return 'float6e2m3fn';
  762. case 'f6E3M2FN': return 'float6e3m2fn';
  763. case 'f8E3M4': return 'float8e3m4';
  764. case 'f8E4M3': return 'float8e4m3';
  765. case 'f8E4M3B11FNUZ': return 'float8e4m3b11fnuz';
  766. case 'f8E4M3FN': return 'float8e4m3fn';
  767. case 'f8E4M3FNUZ': return 'float8e4m3fnuz';
  768. case 'f8E5M2': return 'float8e5m2';
  769. case 'f8E5M2FNUZ': return 'float8e5m2fnuz';
  770. case 'f8E8M0FNU': return 'float8e8m0fnu';
  771. case 'float8': return 'float8';
  772. case 'tf32': return 'tf32';
  773. case 'i1': return 'int1';
  774. case 'i2': return 'int2';
  775. case 'i4': return 'int4';
  776. case 'i8': return 'int8';
  777. case 'i16': return 'int16';
  778. case 'i32': return 'int32';
  779. case 'i48': return 'int48';
  780. case 'i64': return 'int64';
  781. case 'si8': return 'int8';
  782. case 'si16': return 'int16';
  783. case 'si32': return 'int32';
  784. case 'si64': return 'int64';
  785. case 'ui1': return 'uint1';
  786. case 'ui2': return 'uint2';
  787. case 'ui4': return 'uint4';
  788. case 'ui8': return 'uint8';
  789. case 'ui16': return 'uint16';
  790. case 'ui32': return 'uint32';
  791. case 'ui64': return 'uint64';
  792. case 'b8': return 'int8';
  793. case 'unk': return 'unk'; // torch dialect unknown dtype
  794. case '!tf_type.string': return 'string';
  795. case '!tosa.mxint8': return 'int8';
  796. case '!onnx.String': return 'string';
  797. default:
  798. if (value && value.startsWith('!')) {
  799. return value;
  800. }
  801. if (value && value.startsWith('vector<') && value.endsWith('>')) {
  802. return value;
  803. }
  804. if (value && value.startsWith('memref<') && value.endsWith('>')) {
  805. return value;
  806. }
  807. if (value && value.startsWith('tuple<') && value.endsWith('>')) {
  808. return value;
  809. }
  810. if (value && value.startsWith('complex<') && value.endsWith('>')) {
  811. const elementTypeStr = value.substring(8, value.length - 1);
  812. const convertedElementType = mlir.Utility.dataType(elementTypeStr);
  813. return `complex<${convertedElementType}>`;
  814. }
  815. if (value && /^[su]?i[0-9]+$/.test(value)) {
  816. const match = value.match(/^(s|u)?i([0-9]+)$/);
  817. if (match) {
  818. const [, signed, widthStr] = match;
  819. const width = parseInt(widthStr, 10);
  820. if (signed === 'u') {
  821. return `uint${width}`;
  822. } else if (signed === 's') {
  823. return `int${width}`;
  824. }
  825. return `int${width}`;
  826. }
  827. }
  828. throw new mlir.Error(`Unknown data type '${value}'.`);
  829. }
  830. }
  831. static valueType(type) {
  832. if (type === undefined) {
  833. return null;
  834. }
  835. const typeStr = type instanceof _.Type ? type.toString() : type;
  836. if (typeStr.startsWith('!') && !typeStr.startsWith('!torch.vtensor<')) {
  837. return typeStr;
  838. }
  839. if (typeStr.startsWith('tensor<') && typeStr.endsWith('>')) {
  840. const spec = typeStr.substring(7, typeStr.length - 1).trim();
  841. if (spec.startsWith('!')) {
  842. return mlir.Utility.valueType(spec);
  843. }
  844. let i = 0;
  845. const shape = [];
  846. while (i < spec.length) {
  847. if (spec[i] === '?' || spec[i] === '*') {
  848. shape.push('?');
  849. i++;
  850. } else if (/[0-9]/.test(spec[i])) {
  851. let numStr = '';
  852. while (i < spec.length && /[0-9]/.test(spec[i])) {
  853. numStr += spec[i];
  854. i++;
  855. }
  856. const dim = parseInt(numStr, 10);
  857. if (isNaN(dim)) {
  858. shape.push('?');
  859. } else {
  860. shape.push(dim);
  861. }
  862. } else {
  863. break;
  864. }
  865. if (i < spec.length && spec[i] === 'x') {
  866. i++;
  867. } else {
  868. break;
  869. }
  870. }
  871. let dataType = spec.substring(i);
  872. // Find encoding comma, but skip commas inside angle brackets
  873. let depth = 0;
  874. let encodingIndex = -1;
  875. for (let j = 0; j < dataType.length; j++) {
  876. if (dataType[j] === '<') {
  877. depth++;
  878. } else if (dataType[j] === '>') {
  879. depth--;
  880. } else if (dataType[j] === ',' && depth === 0) {
  881. encodingIndex = j;
  882. break;
  883. }
  884. }
  885. if (encodingIndex !== -1) {
  886. dataType = dataType.substring(0, encodingIndex).trim();
  887. }
  888. return new mlir.TensorType(dataType, new mlir.TensorShape(shape));
  889. }
  890. if (typeStr.startsWith('!torch.vtensor<') && typeStr.endsWith('>')) {
  891. const spec = typeStr.substring(15, typeStr.length - 1);
  892. let shape = null;
  893. let dataType = null;
  894. if (spec.startsWith('[')) {
  895. const bracketEnd = spec.indexOf(']');
  896. const shapeStr = spec.substring(0, bracketEnd + 1);
  897. const jsonStr = shapeStr.replace(/\?/g, '"?"');
  898. shape = JSON.parse(jsonStr);
  899. const rest = spec.substring(bracketEnd + 1);
  900. if (rest.startsWith(',')) {
  901. const parts = rest.substring(1).split(',');
  902. dataType = parts[0].trim();
  903. }
  904. } else if (spec.startsWith('*')) {
  905. if (spec.includes(',')) {
  906. const parts = spec.split(',');
  907. dataType = parts[1].trim();
  908. }
  909. } else {
  910. const parts = spec.split(',');
  911. dataType = parts[0].trim();
  912. }
  913. return new mlir.TensorType(dataType, shape ? new mlir.TensorShape(shape) : null);
  914. }
  915. if (typeStr.startsWith('tuple<') && typeStr.endsWith('>')) {
  916. return typeStr;
  917. }
  918. return typeStr;
  919. }
  920. };
  921. _.Block = class {
  922. constructor() {
  923. this.operations = [];
  924. }
  925. };
  926. _.OperationState = class {
  927. constructor(location, name) {
  928. this.location = location;
  929. this.name = name;
  930. if (this.name instanceof _.OperationName === false) {
  931. throw new mlir.Error('Invalid operation name.');
  932. }
  933. this.identifier = name.identifier || name.getStringRef();
  934. delete name.identifier;
  935. this.attributes = new Map();
  936. this.operands = [];
  937. this.types = [];
  938. this.regions = [];
  939. this.propertiesAttr = null;
  940. }
  941. get op() {
  942. return this.name.getStringRef(); // Workaround
  943. }
  944. addRegion() {
  945. const region = {};
  946. this.regions.push(region);
  947. return region;
  948. }
  949. addTypes(newTypes) {
  950. if (!Array.isArray(newTypes) || !newTypes.every((type) => type instanceof _.Type)) {
  951. throw new mlir.Error(`Invalid types '${JSON.stringify(newTypes.filter((type) => type instanceof _.Type === false))}'.`);
  952. }
  953. for (const type of newTypes) {
  954. this.types.push(type);
  955. }
  956. }
  957. addAttribute(name, value) {
  958. if (typeof name !== 'string' || name.length === 0) {
  959. throw new mlir.Error(`Invalid attribute name '${JSON.stringify(name)}'.`);
  960. }
  961. this.attributes.set(name, value);
  962. }
  963. getAttr(name) {
  964. if (this.propertiesAttr instanceof _.DictionaryAttr) {
  965. const value = this.propertiesAttr.get(name);
  966. if (value !== undefined) {
  967. return value;
  968. }
  969. }
  970. return this.attributes.get(name);
  971. }
  972. getAttrDictionary() {
  973. if (this.propertiesAttr instanceof _.DictionaryAttr) {
  974. const result = new Map(this.attributes);
  975. for (const [name, value] of this.propertiesAttr.value) {
  976. result.set(name, value);
  977. }
  978. return result;
  979. }
  980. return this.attributes;
  981. }
  982. };
  983. _.OperationName = class {
  984. constructor(dialect, name) {
  985. this.dialect = dialect;
  986. this.name = name;
  987. }
  988. getStringRef() {
  989. return this.name;
  990. }
  991. getRegisteredInfo() {
  992. return null;
  993. }
  994. };
  995. _.RegisteredOperationName = class extends _.OperationName {
  996. constructor(dialect, name, metadata) {
  997. super(dialect, name);
  998. this.metadata = metadata;
  999. if (metadata.assemblyFormat) {
  1000. const parser = new _.AssemblyFormatParser(metadata);
  1001. this.directives = parser.parse();
  1002. }
  1003. }
  1004. static lookup(name, context) {
  1005. const index = name.indexOf('.');
  1006. if (index !== -1) {
  1007. const dialectName = name.substring(0, index);
  1008. const dialect = context.getOrLoadDialect(dialectName);
  1009. if (dialect) {
  1010. return dialect.getOperation(name);
  1011. }
  1012. }
  1013. return null;
  1014. }
  1015. getRegisteredInfo() {
  1016. return this;
  1017. }
  1018. hasTrait(type) {
  1019. if (this.metadata && Array.isArray(this.metadata.traits)) {
  1020. for (const trait of this.metadata.traits) {
  1021. if (trait.type && trait.type.name === type) {
  1022. return true;
  1023. }
  1024. }
  1025. }
  1026. return false;
  1027. }
  1028. };
  1029. _.Operation = class {
  1030. static create(state) {
  1031. return new _.Operation(state);
  1032. }
  1033. constructor(state) {
  1034. this.name = state.name; // registered operation name
  1035. this.identifier = state.identifier; // original parsed identifier
  1036. this.label = state.label; // human-readable name
  1037. this.attributes = state.attributes;
  1038. this.operands = state.operands;
  1039. this.regions = state.regions;
  1040. this.propertiesAttr = state.propertiesAttr;
  1041. this.loc = state.loc;
  1042. this.results = [];
  1043. if (Array.isArray(state.types)) {
  1044. for (let i = 0; i < state.types.length; i++) {
  1045. const result = new _.OpResult(this, i, state.types[i]);
  1046. this.results.push(result);
  1047. }
  1048. }
  1049. }
  1050. getAttr(name) {
  1051. if (this.propertiesAttr instanceof _.DictionaryAttr) {
  1052. const value = this.propertiesAttr.get(name);
  1053. if (value !== undefined) {
  1054. return value;
  1055. }
  1056. }
  1057. return this.attributes.get(name);
  1058. }
  1059. getAttrDictionary() {
  1060. if (this.propertiesAttr instanceof _.DictionaryAttr) {
  1061. const result = new Map(this.attributes);
  1062. for (const [key, value] of this.propertiesAttr.value) {
  1063. result.set(key, value);
  1064. }
  1065. return result;
  1066. }
  1067. return this.attributes;
  1068. }
  1069. };
  1070. _.UnresolvedOperand = class {
  1071. constructor(location, name, number) {
  1072. this.location = location;
  1073. this.name = name;
  1074. this.number = number;
  1075. }
  1076. toString() {
  1077. return this.number > 0 ? `${this.name}#${this.number}` : this.name;
  1078. }
  1079. };
  1080. _.Value = class {
  1081. constructor(name, type) {
  1082. this.name = name;
  1083. this.type = type;
  1084. }
  1085. toString() {
  1086. return this.name;
  1087. }
  1088. };
  1089. _.OpResult = class extends _.Value {
  1090. constructor(owner, resultNumber, type) {
  1091. super(null, type);
  1092. this.owner = owner;
  1093. this.resultNumber = resultNumber;
  1094. }
  1095. };
  1096. _.Attribute = class {
  1097. };
  1098. _.TypedAttr = class extends _.Attribute {
  1099. constructor(value, type) {
  1100. super();
  1101. this.value = value;
  1102. this.type = type;
  1103. }
  1104. toString() {
  1105. return this.value;
  1106. }
  1107. };
  1108. _.StringAttr = class extends _.TypedAttr {
  1109. constructor(value, type) {
  1110. super(value, type || new _.PrimitiveType('string'));
  1111. }
  1112. toString() {
  1113. return this.value;
  1114. }
  1115. };
  1116. _.UnitAttr = class extends _.Attribute {
  1117. toString() {
  1118. return '';
  1119. }
  1120. };
  1121. _.IntegerAttr = class extends _.Attribute {
  1122. constructor(type, value) {
  1123. super();
  1124. this.value = value;
  1125. this.type = type;
  1126. }
  1127. toString() {
  1128. return this.value.toString();
  1129. }
  1130. };
  1131. _.BoolAttr = class extends _.Attribute {
  1132. constructor(value) {
  1133. super();
  1134. this.value = value;
  1135. this.type = new _.IntegerType('i1');
  1136. }
  1137. toString() {
  1138. return this.value ? 'true' : 'false';
  1139. }
  1140. };
  1141. _.FloatAttr = class extends _.Attribute {
  1142. constructor(type, value) {
  1143. super();
  1144. this.value = value;
  1145. this.type = type;
  1146. }
  1147. toString() {
  1148. return String(this.value);
  1149. }
  1150. };
  1151. _.AffineMapAttr = class extends _.Attribute {
  1152. constructor(map) {
  1153. super();
  1154. this._map = map;
  1155. }
  1156. get value() {
  1157. return this._map;
  1158. }
  1159. toString() {
  1160. return `affine_map<${this._map.toString()}>`;
  1161. }
  1162. };
  1163. _.IntegerSetAttr = class extends _.Attribute {
  1164. constructor(set) {
  1165. super();
  1166. this._set = set;
  1167. }
  1168. get value() {
  1169. return this._set;
  1170. }
  1171. toString() {
  1172. return `affine_set<${this._set.toString()}>`;
  1173. }
  1174. };
  1175. _.SymbolRefAttr = class extends _.Attribute {
  1176. constructor(rootReference, nestedReferences) {
  1177. super();
  1178. this.rootReference = rootReference;
  1179. this.nestedReferences = nestedReferences;
  1180. }
  1181. get value() {
  1182. if (this.nestedReferences && this.nestedReferences.length > 0) {
  1183. return `${this.rootReference}${this.nestedReferences.map((ref) => `::${ref}`).join('')}`;
  1184. }
  1185. return this.rootReference;
  1186. }
  1187. toString() {
  1188. return this.value;
  1189. }
  1190. };
  1191. _.DenseElementsAttr = class extends _.Attribute {
  1192. constructor(value, type) {
  1193. super();
  1194. this.value = value;
  1195. this.type = type;
  1196. }
  1197. };
  1198. _.SparseElementsAttr = class extends _.Attribute {
  1199. constructor(type, indices, values) {
  1200. super();
  1201. this.type = type;
  1202. this.indices = indices;
  1203. this.values = values;
  1204. }
  1205. };
  1206. _.DenseResourceElementsHandle = class {
  1207. constructor(key, blob = null) {
  1208. this.key = key;
  1209. this.blob = blob;
  1210. }
  1211. };
  1212. _.DenseResourceElementsAttr = class extends _.Attribute {
  1213. constructor(type, handle) {
  1214. super();
  1215. this.type = type;
  1216. this.rawHandle = handle;
  1217. }
  1218. get value() {
  1219. return this.rawHandle ? this.rawHandle.blob : null;
  1220. }
  1221. toString() {
  1222. const key = this.rawHandle ? this.rawHandle.key : 'unknown';
  1223. return `dense_resource<${key}>`;
  1224. }
  1225. };
  1226. _.OpaqueAttr = class extends _.Attribute {
  1227. constructor(dialectName, symbolData, type) {
  1228. super();
  1229. this.dialectName = dialectName;
  1230. this.symbolData = symbolData;
  1231. this.type = type;
  1232. }
  1233. get value() {
  1234. return this.toString();
  1235. }
  1236. toString() {
  1237. if (this.symbolData) {
  1238. return `${this.dialectName}.${this.symbolData}`;
  1239. }
  1240. return this.dialectName;
  1241. }
  1242. };
  1243. _.AffineLowPrecOp = {
  1244. LNoOp: '',
  1245. Add: 'Add',
  1246. Sub: 'Sub'
  1247. };
  1248. _.AffineHighPrecOp = {
  1249. HNoOp: '',
  1250. Mul: 'Mul',
  1251. FloorDiv: 'FloorDiv',
  1252. CeilDiv: 'CeilDiv',
  1253. Mod: 'Mod'
  1254. };
  1255. _.AffineExprKind = {
  1256. Add: 'Add',
  1257. Mul: 'Mul',
  1258. Mod: 'Mod',
  1259. FloorDiv: 'FloorDiv',
  1260. CeilDiv: 'CeilDiv',
  1261. Constant: 'Constant',
  1262. DimId: 'DimId',
  1263. SymbolId: 'SymbolId'
  1264. };
  1265. _.AffineExpr = class {
  1266. constructor(kind) {
  1267. this.kind = kind;
  1268. }
  1269. isSymbolicOrConstant() {
  1270. return this.kind === _.AffineExprKind.Constant || this.kind === _.AffineExprKind.SymbolId;
  1271. }
  1272. toString() {
  1273. return '';
  1274. }
  1275. };
  1276. _.AffineDimExpr = class extends _.AffineExpr {
  1277. constructor(position) {
  1278. super(_.AffineExprKind.DimId);
  1279. this._position = position;
  1280. }
  1281. getPosition() {
  1282. return this._position;
  1283. }
  1284. toString() {
  1285. return `d${this._position}`;
  1286. }
  1287. };
  1288. _.AffineSymbolExpr = class extends _.AffineExpr {
  1289. constructor(position) {
  1290. super(_.AffineExprKind.SymbolId);
  1291. this._position = position;
  1292. }
  1293. getPosition() {
  1294. return this._position;
  1295. }
  1296. toString() {
  1297. return `s${this._position}`;
  1298. }
  1299. };
  1300. _.AffineConstantExpr = class extends _.AffineExpr {
  1301. constructor(value) {
  1302. super(_.AffineExprKind.Constant);
  1303. this.value = value;
  1304. }
  1305. toString() {
  1306. return String(this.value);
  1307. }
  1308. };
  1309. _.AffineBinaryOpExpr = class extends _.AffineExpr {
  1310. constructor(kind, lhs, rhs) {
  1311. super(kind);
  1312. this.lhs = lhs;
  1313. this.rhs = rhs;
  1314. }
  1315. isSymbolicOrConstant() {
  1316. return this.lhs.isSymbolicOrConstant() && this.rhs.isSymbolicOrConstant();
  1317. }
  1318. toString() {
  1319. let op = '';
  1320. switch (this.kind) {
  1321. case _.AffineExprKind.Add: op = ' + '; break;
  1322. case _.AffineExprKind.Mul: op = ' * '; break;
  1323. case _.AffineExprKind.Mod: op = ' mod '; break;
  1324. case _.AffineExprKind.FloorDiv: op = ' floordiv '; break;
  1325. case _.AffineExprKind.CeilDiv: op = ' ceildiv '; break;
  1326. default: throw new Error(`Unexpected affine expression kind '${this.kind}'.`);
  1327. }
  1328. return `${this.lhs.toString()}${op}${this.rhs.toString()}`;
  1329. }
  1330. };
  1331. _.AffineMap = class {
  1332. constructor(numDims, numSymbols, results) {
  1333. this._numDims = numDims;
  1334. this._numSymbols = numSymbols;
  1335. this._results = results; // Array of AffineExpr or string for backward compat
  1336. }
  1337. getNumResults() {
  1338. return this._results.length;
  1339. }
  1340. toString() {
  1341. const dims = [];
  1342. for (let i = 0; i < this._numDims; i++) {
  1343. dims.push(`d${i}`);
  1344. }
  1345. const symbols = [];
  1346. for (let i = 0; i < this._numSymbols; i++) {
  1347. symbols.push(`s${i}`);
  1348. }
  1349. const dimsStr = `(${dims.join(', ')})`;
  1350. const symbolsStr = symbols.length > 0 ? `[${symbols.join(', ')}]` : '';
  1351. const resultsStr = this._results.map((r) => r.toString ? r.toString() : String(r)).join(', ');
  1352. return `${dimsStr}${symbolsStr} -> (${resultsStr})`;
  1353. }
  1354. static get(numDims, numSymbols, results) {
  1355. return new _.AffineMap(numDims, numSymbols, results);
  1356. }
  1357. // Backward compatible string-based parse
  1358. static parse(str) {
  1359. const arrowIdx = str.indexOf('->');
  1360. if (arrowIdx === -1) {
  1361. return new _.AffineMap(0, 0, [str]);
  1362. }
  1363. let resultPart = str.substring(arrowIdx + 2).trim();
  1364. const domainIdx = resultPart.indexOf(', domain:');
  1365. if (domainIdx !== -1) {
  1366. resultPart = resultPart.substring(0, domainIdx).trim();
  1367. }
  1368. // Parse result expressions from the result part (e.g., "(d0, d1 + s0)")
  1369. const results = [];
  1370. if (resultPart.startsWith('(')) {
  1371. let depth = 0;
  1372. let start = 1; // Skip opening paren
  1373. for (let i = 0; i < resultPart.length; i++) {
  1374. const ch = resultPart[i];
  1375. if (ch === '(' || ch === '[') {
  1376. depth++;
  1377. } else if (ch === ')' || ch === ']') {
  1378. depth--;
  1379. if (depth === 0) {
  1380. const expr = resultPart.substring(start, i).trim();
  1381. if (expr) {
  1382. results.push(expr);
  1383. }
  1384. break;
  1385. }
  1386. } else if (ch === ',' && depth === 1) {
  1387. const expr = resultPart.substring(start, i).trim();
  1388. if (expr) {
  1389. results.push(expr);
  1390. }
  1391. start = i + 1;
  1392. }
  1393. }
  1394. } else {
  1395. results.push(resultPart);
  1396. }
  1397. // For backward compat, store string representation of results
  1398. return new _.AffineMap(0, 0, results.length > 0 ? results : [str]);
  1399. }
  1400. };
  1401. // Integer set for affine_set constraints
  1402. _.IntegerSet = class {
  1403. constructor(numDims, numSymbols, constraints, eqFlags) {
  1404. this._numDims = numDims;
  1405. this._numSymbols = numSymbols;
  1406. this._constraints = constraints; // Array of AffineExpr
  1407. this._eqFlags = eqFlags; // Array of bool (true = equality, false = inequality)
  1408. }
  1409. getNumConstraints() {
  1410. return this._constraints.length;
  1411. }
  1412. getConstraints() {
  1413. return this._constraints;
  1414. }
  1415. getConstraint(idx) {
  1416. return this._constraints[idx];
  1417. }
  1418. getEqFlags() {
  1419. return this._eqFlags;
  1420. }
  1421. isEq(idx) {
  1422. return this._eqFlags[idx];
  1423. }
  1424. toString() {
  1425. const dims = [];
  1426. for (let i = 0; i < this._numDims; i++) {
  1427. dims.push(`d${i}`);
  1428. }
  1429. const symbols = [];
  1430. for (let i = 0; i < this._numSymbols; i++) {
  1431. symbols.push(`s${i}`);
  1432. }
  1433. const dimsStr = `(${dims.join(', ')})`;
  1434. const symbolsStr = symbols.length > 0 ? `[${symbols.join(', ')}]` : '';
  1435. const constraintsStr = this._constraints.map((c, i) => {
  1436. const exprStr = c.toString ? c.toString() : String(c);
  1437. return this._eqFlags[i] ? `${exprStr} == 0` : `${exprStr} >= 0`;
  1438. }).join(', ');
  1439. return `${dimsStr}${symbolsStr} : (${constraintsStr})`;
  1440. }
  1441. static get(numDims, numSymbols, constraints, eqFlags) {
  1442. return new _.IntegerSet(numDims, numSymbols, constraints, eqFlags);
  1443. }
  1444. };
  1445. _.IndexingMap = class {
  1446. constructor(affineMap) {
  1447. this._affineMap = affineMap;
  1448. }
  1449. GetAffineMap() {
  1450. return this._affineMap;
  1451. }
  1452. };
  1453. _.IndexingMapAttr = class extends _.Attribute {
  1454. constructor(indexingMap) {
  1455. super();
  1456. this._indexingMap = indexingMap;
  1457. }
  1458. get value() {
  1459. return this.toString();
  1460. }
  1461. getIndexingMap() {
  1462. return this._indexingMap;
  1463. }
  1464. static parse(parser /*, type */) {
  1465. parser.parseLess();
  1466. const indexingMap = _.IndexingMapAttr.parseChainOfStringsAsIndexingMap(parser);
  1467. parser.parseGreater();
  1468. return new _.IndexingMapAttr(indexingMap);
  1469. }
  1470. static parseChainOfStringsAsIndexingMap(parser) {
  1471. let indexingMapStr = '';
  1472. let str = parser.parseOptionalString();
  1473. while (str !== null) {
  1474. indexingMapStr += str;
  1475. str = parser.parseOptionalString();
  1476. }
  1477. return _.IndexingMapAttr.parseIndexingMap(indexingMapStr);
  1478. }
  1479. static parseIndexingMap(str) {
  1480. const domainIdx = str.indexOf(', domain:');
  1481. const mapStr = domainIdx >= 0 ? str.substring(0, domainIdx) : str.replace(/,$/, '');
  1482. const affineMap = _.AffineMap.parse(mapStr);
  1483. return new _.IndexingMap(affineMap);
  1484. }
  1485. toString() {
  1486. return `#xla.indexing_map<"${this._indexingMap.GetAffineMap().toString()}">`;
  1487. }
  1488. };
  1489. _.ArrayAttr = class extends _.Attribute {
  1490. constructor(elements) {
  1491. super();
  1492. this.elements = elements; // Array of Attribute objects
  1493. }
  1494. get value() {
  1495. return this.elements.map((e) => e && e.value !== undefined ? e.value : e);
  1496. }
  1497. toString() {
  1498. return `${this.elements.map((e) => e && e.toString ? e.toString() : String(e)).join(', ')}`;
  1499. }
  1500. };
  1501. _.DenseI64ArrayAttr = class extends _.Attribute {
  1502. constructor(values) {
  1503. super();
  1504. this._values = values; // Array of i64 integers
  1505. }
  1506. get value() {
  1507. return this._values;
  1508. }
  1509. toString() {
  1510. return `[${this._values.join(', ')}]`;
  1511. }
  1512. static parse(parser) {
  1513. if (parser.getToken().isNot(_.Token.l_square)) {
  1514. return null;
  1515. }
  1516. parser.consumeToken(_.Token.l_square);
  1517. const values = [];
  1518. while (parser.getToken().isNot(_.Token.r_square)) {
  1519. const value = parser.parseOptionalInteger();
  1520. if (value === null) {
  1521. break;
  1522. }
  1523. values.push(value);
  1524. parser.parseOptionalComma();
  1525. }
  1526. parser.consumeToken(_.Token.r_square);
  1527. return new _.DenseI64ArrayAttr(values);
  1528. }
  1529. };
  1530. _.DictionaryAttr = class extends _.Attribute {
  1531. constructor(value) {
  1532. super();
  1533. this._value = value; // Map of name -> Attribute
  1534. }
  1535. get value() {
  1536. return this._value;
  1537. }
  1538. get(name) {
  1539. return this._value.get(name);
  1540. }
  1541. toString() {
  1542. const entries = Array.from(this._value.entries())
  1543. .map(([k, v]) => `${k} = ${v && v.toString ? v.toString() : String(v)}`);
  1544. return `{${entries.join(', ')}}`;
  1545. }
  1546. };
  1547. _.DenseArrayAttr = class extends _.Attribute {
  1548. constructor(type, size, data) {
  1549. super();
  1550. this.type = type;
  1551. this.size = size;
  1552. if (data instanceof Uint8Array) {
  1553. this.values = null;
  1554. this.data = data;
  1555. } else {
  1556. this.values = data;
  1557. }
  1558. }
  1559. get value() {
  1560. if (this.values === null) {
  1561. const blob = this.data;
  1562. const typeStr = this.type.toString();
  1563. const view = new DataView(blob.buffer, blob.byteOffset, blob.length);
  1564. const values = [];
  1565. if (typeStr.startsWith('i') || typeStr.startsWith('si') || typeStr.startsWith('ui') || typeStr === 'index') {
  1566. const match = typeStr.match(/[su]?i(\d+)/);
  1567. const bitWidth = match ? parseInt(match[1], 10) : 64;
  1568. const unsigned = typeStr.startsWith('ui');
  1569. const byteWidth = Math.ceil(bitWidth / 8);
  1570. const size = blob.length / byteWidth;
  1571. for (let i = 0; i < size; i++) {
  1572. if (bitWidth <= 8) {
  1573. values.push(unsigned ? view.getUint8(i * byteWidth) : view.getInt8(i * byteWidth));
  1574. } else if (bitWidth <= 16) {
  1575. values.push(unsigned ? view.getUint16(i * byteWidth, true) : view.getInt16(i * byteWidth, true));
  1576. } else if (bitWidth <= 32) {
  1577. values.push(unsigned ? view.getUint32(i * byteWidth, true) : view.getInt32(i * byteWidth, true));
  1578. } else {
  1579. values.push(unsigned ? view.getBigUint64(i * byteWidth, true) : view.getBigInt64(i * byteWidth, true));
  1580. }
  1581. }
  1582. } else if (typeStr === 'f32') {
  1583. const size = blob.length / 4;
  1584. for (let i = 0; i < size; i++) {
  1585. values.push(view.getFloat32(i * 4, true));
  1586. }
  1587. } else if (typeStr === 'f64') {
  1588. const size = blob.length / 8;
  1589. for (let i = 0; i < size; i++) {
  1590. values.push(view.getFloat64(i * 8, true));
  1591. }
  1592. } else if (typeStr === 'f16') {
  1593. const size = blob.length / 2;
  1594. for (let i = 0; i < size; i++) {
  1595. values.push(view.getFloat16(i * 2, true));
  1596. }
  1597. }
  1598. this.values = values;
  1599. this.data = null;
  1600. }
  1601. return this.values;
  1602. }
  1603. toString() {
  1604. const typeStr = this.type ? this.type.toString() : '';
  1605. return `array<${typeStr}: ${this.value.join(', ')}>`;
  1606. }
  1607. };
  1608. _.TypeAttrOf = class extends _.Attribute {
  1609. constructor(type) {
  1610. super();
  1611. this.type = type; // the type IS the value
  1612. }
  1613. toString() {
  1614. return this.type.toString();
  1615. }
  1616. };
  1617. _.ConvDimensionNumbersAttr = class extends _.Attribute {
  1618. constructor(input, kernel, output) {
  1619. super();
  1620. this.input = input;
  1621. this.kernel = kernel;
  1622. this.output = output;
  1623. }
  1624. toString() {
  1625. const formatDim = (dims) => `[${dims.join(', ')}]`;
  1626. return `${formatDim(this.input)}x${formatDim(this.kernel)}->${formatDim(this.output)}`;
  1627. }
  1628. };
  1629. _.StringRef = class {
  1630. constructor(value, position) {
  1631. this.value = value;
  1632. this.position = position;
  1633. }
  1634. data() {
  1635. return this.position;
  1636. }
  1637. str() {
  1638. return this.value;
  1639. }
  1640. drop_front(n = 1) {
  1641. return this.value.substring(n);
  1642. }
  1643. getAsInteger(radix) {
  1644. const str = this.value;
  1645. if (str.length === 0) {
  1646. return null;
  1647. }
  1648. const value = radix === 0 ? Number(str) : parseInt(str, radix);
  1649. if (!Number.isInteger(value)) {
  1650. return null;
  1651. }
  1652. return value;
  1653. }
  1654. toString() {
  1655. return this.value;
  1656. }
  1657. };
  1658. _.Type = class {
  1659. constructor(value) {
  1660. if (value && value instanceof _.RankedTensorType === false && value.startsWith('tensor<')) {
  1661. // Do not remove. Investigate why RankedTensorType is not getting parsed.
  1662. throw new mlir.Error(`Invalid type '${value}'.`);
  1663. }
  1664. this._value = value;
  1665. }
  1666. get name() {
  1667. return this._value;
  1668. }
  1669. toString() {
  1670. return this._value;
  1671. }
  1672. };
  1673. _.OpaqueType = class extends _.Type {
  1674. constructor(dialect, symbolData) {
  1675. super();
  1676. this.dialect = dialect;
  1677. this.symbolData = symbolData;
  1678. }
  1679. toString() {
  1680. return `!${this.dialect}${this.symbolData}`;
  1681. }
  1682. };
  1683. _.util = {};
  1684. _.util.VariantType = class extends _.Type {
  1685. toString() {
  1686. return '?';
  1687. }
  1688. };
  1689. _.util.ListType = class extends _.Type {
  1690. constructor(elementType) {
  1691. super();
  1692. this.elementType = elementType;
  1693. }
  1694. toString() {
  1695. return `!util.list<${this.elementType}>`;
  1696. }
  1697. };
  1698. _.PrimitiveType = class extends _.Type {
  1699. };
  1700. _.IntegerType = class extends _.Type {
  1701. };
  1702. _.IntegerType.kMaxWidth = (1 << 24) - 1;
  1703. _.FloatType = class extends _.Type {
  1704. };
  1705. _.NoneType = class extends _.Type {
  1706. constructor() {
  1707. super('none');
  1708. }
  1709. };
  1710. _.IndexType = class extends _.Type {
  1711. constructor() {
  1712. super('index');
  1713. }
  1714. };
  1715. _.FunctionType = class extends _.Type {
  1716. constructor(inputs, results) {
  1717. super(null);
  1718. this.inputs = inputs || [];
  1719. this.results = results || [];
  1720. }
  1721. toString() {
  1722. const inputs = this.inputs.map((t) => t.toString());
  1723. const results = this.results.map((t) => t.toString());
  1724. const result = results.length === 1 ? results[0] : `(${results.join(', ')})`;
  1725. return `(${inputs.join(', ')}) -> ${result}`;
  1726. }
  1727. };
  1728. _.ComplexType = class extends _.Type {
  1729. constructor(elementType) {
  1730. super(null);
  1731. this.elementType = elementType;
  1732. }
  1733. toString() {
  1734. const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;
  1735. return `complex<${elementTypeStr}>`;
  1736. }
  1737. };
  1738. _.ShapedType = class extends _.Type {
  1739. getNumElements() {
  1740. if (this.shape.some((d) => d < 0 || d === _.ShapedType.kDynamic)) {
  1741. return 0;
  1742. }
  1743. return this.shape.length === 0 ? 1 : this.shape.reduce((a, b) => a * b, 1);
  1744. }
  1745. };
  1746. _.ShapedType.kDynamic = Number.MIN_SAFE_INTEGER;
  1747. _.RankedTensorType = class extends _.ShapedType {
  1748. constructor(shape, elementType, encoding) {
  1749. super(null);
  1750. this.shape = shape || [];
  1751. this.elementType = elementType;
  1752. this.encoding = encoding;
  1753. }
  1754. toString() {
  1755. const shapeStr = this.shape.map((d) => d < 0 ? '?' : d).join('x');
  1756. const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;
  1757. const prefix = shapeStr ? `${shapeStr}x` : '';
  1758. if (this.encoding) {
  1759. return `tensor<${prefix}${elementTypeStr}, ${this.encoding}>`;
  1760. }
  1761. return `tensor<${prefix}${elementTypeStr}>`;
  1762. }
  1763. };
  1764. _.UnrankedTensorType = class extends _.Type {
  1765. constructor(elementType) {
  1766. super(null);
  1767. this.elementType = elementType;
  1768. }
  1769. toString() {
  1770. const elementTypeStr = this.elementType.toString();
  1771. return `tensor<*x${elementTypeStr}>`;
  1772. }
  1773. };
  1774. _.VectorType = class extends _.ShapedType {
  1775. constructor(shape, elementType, scalableDims) {
  1776. super(null);
  1777. this.shape = shape || [];
  1778. this.elementType = elementType;
  1779. this.scalableDims = scalableDims || [];
  1780. }
  1781. toString() {
  1782. const parts = this.shape.map((d, i) => {
  1783. const isScalable = this.scalableDims[i];
  1784. return isScalable ? `[${d}]` : String(d);
  1785. });
  1786. const shapeStr = parts.join('x');
  1787. const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;
  1788. const prefix = shapeStr ? `${shapeStr}x` : '';
  1789. return `vector<${prefix}${elementTypeStr}>`;
  1790. }
  1791. };
  1792. _.MemRefType = class extends _.ShapedType {
  1793. constructor(shape, elementType, layout, memorySpace) {
  1794. super(null);
  1795. this.shape = shape || [];
  1796. this.elementType = elementType;
  1797. this.layout = layout || null;
  1798. this.memorySpace = memorySpace || null;
  1799. }
  1800. toString() {
  1801. const shapeStr = this.shape.map((d) => d < 0 ? '?' : d).join('x');
  1802. const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;
  1803. const prefix = shapeStr ? `${shapeStr}x` : '';
  1804. let result = `memref<${prefix}${elementTypeStr}`;
  1805. if (this.layout) {
  1806. const layoutStr = typeof this.layout === 'object' ? JSON.stringify(this.layout) : this.layout;
  1807. result += `, ${layoutStr}`;
  1808. }
  1809. if (this.memorySpace) {
  1810. const memorySpaceStr = typeof this.memorySpace === 'object' ? JSON.stringify(this.memorySpace) : this.memorySpace;
  1811. result += `, ${memorySpaceStr}`;
  1812. }
  1813. result += '>';
  1814. return result;
  1815. }
  1816. };
  1817. _.UnrankedMemRefType = class extends _.Type {
  1818. constructor(elementType, memorySpace) {
  1819. super(null);
  1820. this.elementType = elementType;
  1821. this.memorySpace = memorySpace || null;
  1822. }
  1823. toString() {
  1824. const elementTypeStr = this.elementType?.toString ? this.elementType.toString() : this.elementType;
  1825. let result = `memref<*x${elementTypeStr}`;
  1826. if (this.memorySpace) {
  1827. const memorySpaceStr = typeof this.memorySpace === 'object' ? JSON.stringify(this.memorySpace) : this.memorySpace;
  1828. result += `, ${memorySpaceStr}`;
  1829. }
  1830. result += '>';
  1831. return result;
  1832. }
  1833. };
  1834. _.TupleType = class extends _.Type {
  1835. constructor(types) {
  1836. super(null);
  1837. this.types = types || [];
  1838. }
  1839. getTypes() {
  1840. return this.types;
  1841. }
  1842. getNumTypes() {
  1843. return this.types.length;
  1844. }
  1845. getType(index) {
  1846. return this.types[index];
  1847. }
  1848. toString() {
  1849. const typeStrs = this.types.map((t) => t?.toString ? t.toString() : t);
  1850. return `tuple<${typeStrs.join(', ')}>`;
  1851. }
  1852. };
  1853. _.SMLoc = class {
  1854. constructor(decoder, position) {
  1855. this.decoder = decoder;
  1856. this.position = position || 0;
  1857. }
  1858. copy() {
  1859. return new _.SMLoc(this.decoder, this.position);
  1860. }
  1861. toString() {
  1862. let line = 1;
  1863. let column = 1;
  1864. const position = this.decoder.position;
  1865. this.decoder.position = 0;
  1866. let c = '';
  1867. do {
  1868. if (this.decoder.position === this.position) {
  1869. this.decoder.position = position;
  1870. return `at ${line}:${column}.`;
  1871. }
  1872. c = this.decoder.decode();
  1873. if (c === '\n') {
  1874. line++;
  1875. column = 1;
  1876. } else {
  1877. column++;
  1878. }
  1879. }
  1880. while (c !== undefined);
  1881. this.decoder.position = position;
  1882. return `at ${line}:${column}.`;
  1883. }
  1884. };
  1885. _.Token = class {
  1886. constructor(decoder) {
  1887. this.loc = new _.SMLoc(decoder);
  1888. this.kind = null;
  1889. this.spelling = new _.StringRef('', decoder.position);
  1890. }
  1891. is(kind) {
  1892. return this.kind === kind;
  1893. }
  1894. isAny(...args) {
  1895. return args.some((kind) => this.kind === kind);
  1896. }
  1897. isNot(kind) {
  1898. return this.kind !== kind;
  1899. }
  1900. isKeyword() {
  1901. return this.kind.startsWith('kw_');
  1902. }
  1903. getSpelling() {
  1904. return this.spelling;
  1905. }
  1906. getUnsignedIntegerValue() {
  1907. const isHex = this.spelling.str().length > 1 && this.spelling.str()[1] === 'x';
  1908. const value = this.spelling.getAsInteger(isHex ? 0 : 10);
  1909. if (value === null || value < 0 || value > 0xFFFFFFFF) {
  1910. return null;
  1911. }
  1912. return value;
  1913. }
  1914. getUInt64IntegerValue() {
  1915. const spelling = this.spelling.str();
  1916. if (/^-?(\d+|0x[\da-f]+|0o[0-7]+|0b[01]+)$/i.test(spelling)) {
  1917. return BigInt(spelling);
  1918. }
  1919. return null;
  1920. }
  1921. getFloatingPointValue() {
  1922. const result = parseFloat(this.spelling.str());
  1923. if (isNaN(result)) {
  1924. return null;
  1925. }
  1926. return result;
  1927. }
  1928. getIntTypeBitwidth() {
  1929. const spelling = this.spelling.str();
  1930. const start = spelling[0] === 'i' ? 1 : 2;
  1931. const result = parseInt(spelling.slice(start), 10);
  1932. if (isNaN(result)) {
  1933. return null;
  1934. }
  1935. return result;
  1936. }
  1937. getIntTypeSignedness() {
  1938. const spelling = this.spelling.str();
  1939. if (spelling[0] === 'i') {
  1940. return null;
  1941. }
  1942. if (spelling[0] === 's') {
  1943. return true;
  1944. }
  1945. return false;
  1946. }
  1947. getHexStringValue() {
  1948. const spelling = this.spelling.str();
  1949. const bytes = spelling.slice(1, -1);
  1950. if (!bytes.startsWith('0x') || (bytes.length - 2) % 2 !== 0) {
  1951. return null;
  1952. }
  1953. const hex = bytes.slice(2);
  1954. const result = [];
  1955. for (let i = 0; i < hex.length; i += 2) {
  1956. const hi = parseInt(hex[i], 16);
  1957. const lo = parseInt(hex[i + 1], 16);
  1958. if (isNaN(hi) || isNaN(lo)) {
  1959. return null;
  1960. }
  1961. result.push((hi << 4) | lo);
  1962. }
  1963. return result;
  1964. }
  1965. getSymbolReference() {
  1966. const nameStr = this.spelling.str().slice(1);
  1967. if (nameStr[0] === '"') {
  1968. return this.getStringValue();
  1969. }
  1970. return nameStr;
  1971. }
  1972. getHashIdentifierNumber() {
  1973. const str = this.spelling.str().slice(1);
  1974. const result = parseInt(str, 10);
  1975. if (isNaN(result)) {
  1976. return null;
  1977. }
  1978. return result;
  1979. }
  1980. getStringValue() {
  1981. let bytes = this.spelling.str();
  1982. bytes = bytes.slice(1);
  1983. bytes = bytes.slice(0, -1);
  1984. if (this.kind === _.Token.at_identifier) {
  1985. bytes = bytes.slice(1);
  1986. }
  1987. if (!bytes.includes('\\')) {
  1988. return bytes;
  1989. }
  1990. const parts = [];
  1991. for (let i = 0; i < bytes.length;) {
  1992. const c = bytes[i++];
  1993. if (c !== '\\') {
  1994. parts.push(c);
  1995. continue;
  1996. }
  1997. const c1 = bytes[i++];
  1998. switch (c1) {
  1999. case '"':
  2000. case '\\':
  2001. parts.push(c1);
  2002. continue;
  2003. case 'n':
  2004. parts.push('\n');
  2005. continue;
  2006. case 't':
  2007. parts.push('\t');
  2008. continue;
  2009. default:
  2010. break;
  2011. }
  2012. const c2 = bytes[i++];
  2013. const hexValue = (parseInt(c1, 16) << 4) | parseInt(c2, 16);
  2014. parts.push(String.fromCharCode(hexValue));
  2015. }
  2016. return parts.join('');
  2017. }
  2018. };
  2019. _.Token.arrow = '->';
  2020. _.Token.at_identifier = '@';
  2021. _.Token.bare_identifier = 'id';
  2022. _.Token.caret_identifier = '^';
  2023. _.Token.colon = ':';
  2024. _.Token.comma = ',';
  2025. _.Token.ellipsis = 'ellipsis';
  2026. _.Token.eof = 'eof';
  2027. _.Token.equal = '=';
  2028. _.Token.exclamation_identifier = '!';
  2029. _.Token.file_metadata_begin = '{-#';
  2030. _.Token.file_metadata_end = '#-}';
  2031. _.Token.floatliteral = 'float';
  2032. _.Token.greater = '>';
  2033. _.Token.hash_identifier = '#';
  2034. _.Token.integer = 'int';
  2035. _.Token.inttype = 'inttype';
  2036. _.Token.kw_ceildiv = 'kw_ceildiv';
  2037. _.Token.kw_floordiv = 'kw_floordiv';
  2038. _.Token.kw_mod = 'kw_mod';
  2039. _.Token.l_brace = '{';
  2040. _.Token.l_paren = '(';
  2041. _.Token.l_square = '[';
  2042. _.Token.less = '<';
  2043. _.Token.minus = 'minus';
  2044. _.Token.percent_identifier = '%';
  2045. _.Token.plus = 'plus';
  2046. _.Token.question = '?';
  2047. _.Token.r_brace = '}';
  2048. _.Token.r_paren = ')';
  2049. _.Token.r_square = ']';
  2050. _.Token.slash = '/';
  2051. _.Token.star = '*';
  2052. _.Token.string = 'string';
  2053. _.Token.vertical_bar = '|';
  2054. _.Token.kw_affine_map = 'kw_affine_map';
  2055. _.Token.kw_affine_set = 'kw_affine_set';
  2056. _.Token.kw_array = 'kw_array';
  2057. _.Token.kw_dense = 'kw_dense';
  2058. _.Token.kw_dense_resource = 'kw_dense_resource';
  2059. _.Token.kw_distinct = 'kw_distinct';
  2060. _.Token.kw_loc = 'kw_loc';
  2061. _.Token.kw_sparse = 'kw_sparse';
  2062. _.Token.kw_strided = 'kw_strided';
  2063. _.Token.kw_unit = 'kw_unit';
  2064. _.Token.kw_offset = 'kw_offset';
  2065. _.Token.kw_symbol = 'kw_symbol';
  2066. _.Token.kw_true = 'kw_true';
  2067. _.Token.kw_false = 'kw_false';
  2068. _.Lexer = class {
  2069. constructor(decoder) {
  2070. this._decoder = decoder;
  2071. this._currentPosition = this._decoder.position;
  2072. this._current = this._decoder.decode();
  2073. this._nextPosition = this._decoder.position;
  2074. this._next = this._decoder.decode();
  2075. this._tokens = [new _.Token(decoder), new _.Token(decoder), new _.Token(decoder), new _.Token(decoder)];
  2076. this._index = 0;
  2077. this._errorLoc = new _.SMLoc(decoder);
  2078. }
  2079. location() {
  2080. const loc = new _.SMLoc(this._decoder, this._position);
  2081. return loc.toString();
  2082. }
  2083. lexToken() {
  2084. this._position = this._currentPosition;
  2085. while (this._current) {
  2086. switch (this._current) {
  2087. case ' ':
  2088. case '\t':
  2089. case '\n':
  2090. case '\r':
  2091. this._skipWhitespace();
  2092. this._position = this._currentPosition;
  2093. continue;
  2094. case '/':
  2095. if (this._peek() !== '/') {
  2096. this._read();
  2097. return this.formToken('/', '/');
  2098. }
  2099. this.lexComment();
  2100. this._position = this._currentPosition;
  2101. continue;
  2102. case '.':
  2103. this._read();
  2104. if (this._current === '.' && this._next === '.') {
  2105. this._read();
  2106. this._read();
  2107. return this.formToken('ellipsis', '...');
  2108. }
  2109. throw new mlir.Error(`Expected three consecutive dots for an ellipsis ${this.location()}`);
  2110. case '-':
  2111. if (this._peek() === '>') {
  2112. this._read();
  2113. this._read();
  2114. return this.formToken('->', '->');
  2115. }
  2116. this._read();
  2117. return this.formToken('minus', '-');
  2118. case '+':
  2119. this._read();
  2120. return this.formToken('plus', '+');
  2121. case '"':
  2122. return this.lexString();
  2123. case '@':
  2124. return this.lexPrefixedIdentifier('@');
  2125. case '%':
  2126. return this.lexPrefixedIdentifier('%');
  2127. case '#':
  2128. if (this._peek() === '-') {
  2129. const position = this._decoder.position;
  2130. const next = this._decoder.decode();
  2131. this._decoder.position = position;
  2132. if (next === '}') {
  2133. this._read();
  2134. this._read();
  2135. this._read();
  2136. return this.formToken('#-}', '#-}');
  2137. }
  2138. }
  2139. return this.lexPrefixedIdentifier('#');
  2140. case '!':
  2141. return this.lexPrefixedIdentifier('!');
  2142. case '^':
  2143. return this.lexPrefixedIdentifier('^');
  2144. case '=':
  2145. this._read();
  2146. return this.formToken('=', '=');
  2147. case ':':
  2148. this._read();
  2149. return this.formToken(':', ':');
  2150. case ',':
  2151. case '(':
  2152. case ')':
  2153. case '}':
  2154. case '[':
  2155. case ']':
  2156. case '<':
  2157. case '>':
  2158. case '?':
  2159. case '*':
  2160. case '|': {
  2161. const value = this._read();
  2162. return this.formToken(value, value);
  2163. }
  2164. case '{':
  2165. if (this._peek() === '-') {
  2166. const position = this._decoder.position;
  2167. const next = this._decoder.decode();
  2168. this._decoder.position = position;
  2169. if (next === '#') {
  2170. this._read();
  2171. this._read();
  2172. this._read();
  2173. return this.formToken('{-#', '{-#');
  2174. }
  2175. }
  2176. this._read();
  2177. return this.formToken('{', '{');
  2178. default:
  2179. if (/[a-zA-Z_]/.test(this._current)) {
  2180. return this.lexBareIdentifierOrKeyword();
  2181. }
  2182. if (/[0-9]/.test(this._current)) {
  2183. return this.lexNumber();
  2184. }
  2185. throw new mlir.Error(`Unexpected character '${this._current}' ${this.location()}`);
  2186. }
  2187. }
  2188. return this.formToken('eof', null);
  2189. }
  2190. resetPointer(newPointer) {
  2191. if (newPointer < 0) {
  2192. throw new mlir.Error('Invalid negative offset.');
  2193. }
  2194. this._decoder.position = newPointer;
  2195. this._nextPosition = this._decoder.position;
  2196. this._next = this._decoder.decode();
  2197. this._read();
  2198. }
  2199. _read() {
  2200. const current = this._current;
  2201. this._current = this._next;
  2202. this._currentPosition = this._nextPosition;
  2203. this._nextPosition = this._decoder.position;
  2204. this._next = this._decoder.decode();
  2205. return current;
  2206. }
  2207. _peek() {
  2208. return this._next;
  2209. }
  2210. _eat(value) {
  2211. if (this._current === value) {
  2212. this._read();
  2213. return true;
  2214. }
  2215. return false;
  2216. }
  2217. _skipWhitespace() {
  2218. while (this._current !== undefined && (this._current === ' ' || this._current === '\t' || this._current === '\n' || this._current === '\r')) {
  2219. this._read();
  2220. }
  2221. }
  2222. lexComment() {
  2223. this._read('/');
  2224. if (this._current !== '/') {
  2225. throw new mlir.Error(`Invalid comment.`);
  2226. }
  2227. while (this._current && this._current !== '\n' && this._current !== '\r') {
  2228. this._read();
  2229. }
  2230. }
  2231. lexNumber() {
  2232. let v = '';
  2233. let type = 'int';
  2234. while (this._current && /[0-9]/.test(this._current)) {
  2235. v += this._read();
  2236. }
  2237. if (v === '0' && this._current === 'x' && /[0-9a-fA-F]/.test(this._peek())) {
  2238. v += this._read();
  2239. while (this._current && /[0-9a-fA-F]/.test(this._current)) {
  2240. v += this._read();
  2241. }
  2242. return this.formToken(type, v);
  2243. }
  2244. if (this._current === '.') {
  2245. v += this._read();
  2246. type = 'float';
  2247. while (this._current && /[0-9]/.test(this._current)) {
  2248. v += this._read();
  2249. }
  2250. if (this._current === 'e' || this._current === 'E') {
  2251. const next1 = this._peek();
  2252. let next2 = '';
  2253. if (next1 === '+' || next1 === '-') {
  2254. const position = this._decoder.position;
  2255. next2 = this._decoder.decode();
  2256. this._decoder.position = position;
  2257. }
  2258. if (/[0-9]/.test(next1) || ((next1 === '+' || next1 === '-') && /[0-9]/.test(next2))) {
  2259. v += this._read();
  2260. if (this._current === '+' || this._current === '-') {
  2261. v += this._read();
  2262. }
  2263. while (this._current && /[0-9]/.test(this._current)) {
  2264. v += this._read();
  2265. }
  2266. }
  2267. }
  2268. return this.formToken(type, v);
  2269. }
  2270. return this.formToken(type, v);
  2271. }
  2272. lexString() {
  2273. const parts = ['"'];
  2274. this._read();
  2275. let chunk = '';
  2276. while (this._current && this._current !== '"') {
  2277. if (this._current === '\n' || this._current === '\v' ||
  2278. this._current === '\f' || this._current === '\r') {
  2279. throw new mlir.Error(`Expected '"' in string literal ${this.location()}`);
  2280. }
  2281. if (this._current === '\\') {
  2282. if (chunk) {
  2283. parts.push(chunk);
  2284. chunk = '';
  2285. }
  2286. parts.push(this._current);
  2287. this._read();
  2288. if (this._current === '"' || this._current === '\\' || this._current === 'n' || this._current === 't') {
  2289. parts.push(this._current);
  2290. this._read();
  2291. } else if (this._current && /[0-9a-fA-F]/.test(this._current) && this._next && /[0-9a-fA-F]/.test(this._next)) {
  2292. parts.push(this._current);
  2293. this._read();
  2294. parts.push(this._current);
  2295. this._read();
  2296. } else {
  2297. throw new mlir.Error(`Unknown escape in string literal ${this.location()}`);
  2298. }
  2299. } else {
  2300. chunk += this._current;
  2301. if (chunk.length >= 4096) {
  2302. parts.push(chunk);
  2303. chunk = '';
  2304. }
  2305. this._read();
  2306. }
  2307. }
  2308. if (chunk) {
  2309. parts.push(chunk);
  2310. }
  2311. if (this._eat('"')) {
  2312. parts.push('"');
  2313. return this.formToken(_.Token.string, parts.join(''));
  2314. }
  2315. throw new mlir.Error('Unterminated string literal');
  2316. }
  2317. lexBareIdentifierOrKeyword() {
  2318. let result = '';
  2319. while (this._current && (/[a-zA-Z_$.]/.test(this._current) || /[0-9]/.test(this._current))) {
  2320. result += this._read();
  2321. }
  2322. const isAllDigit = (str) => /^[0-9]+$/.test(str);
  2323. if ((result.length > 1 && result[0] === 'i' && isAllDigit(result.slice(1))) ||
  2324. (result.length > 2 && result[1] === 'i' && (result[0] === 's' || result[0] === 'u') && isAllDigit(result.slice(2)))) {
  2325. return this.formToken('inttype', result);
  2326. }
  2327. switch (result) {
  2328. case 'loc':
  2329. case 'affine_map':
  2330. case 'affine_set':
  2331. case 'dense':
  2332. case 'dense_resource':
  2333. case 'sparse':
  2334. case 'array':
  2335. case 'strided':
  2336. case 'distinct':
  2337. case 'unit':
  2338. case 'floordiv':
  2339. case 'ceildiv':
  2340. case 'mod':
  2341. case 'offset':
  2342. case 'symbol':
  2343. return this.formToken(`kw_${result}`, result);
  2344. case 'true':
  2345. return this.formToken(_.Token.kw_true, result);
  2346. case 'false':
  2347. return this.formToken(_.Token.kw_false, result);
  2348. case 'unknown':
  2349. return this.formToken(_.Token.bare_identifier, result);
  2350. default:
  2351. return this.formToken(_.Token.bare_identifier, result);
  2352. }
  2353. }
  2354. lexPrefixedIdentifier(prefix) {
  2355. let result = prefix;
  2356. this._read();
  2357. if (prefix === '@' && this._current === '"') {
  2358. result += this.lexString().getSpelling().str();
  2359. return this.formToken(prefix, result);
  2360. }
  2361. if (prefix === '@') {
  2362. // symbol-ref-id ::= `@` (bare-id | string-literal)
  2363. // bare-id ::= (letter|[_]) (letter|digit|[_$.])*
  2364. if (this._current && /[a-zA-Z_]/.test(this._current)) {
  2365. while (this._current && /[a-zA-Z0-9_$.]/.test(this._current)) {
  2366. result += this._read();
  2367. }
  2368. } else if (result.length === 1) {
  2369. throw new mlir.Error(`@ identifier expected to start with letter or '_' ${this.location()}`);
  2370. }
  2371. } else if (this._current && /[0-9]/.test(this._current)) {
  2372. // suffix-id ::= digit+ | ...
  2373. while (this._current && /[0-9]/.test(this._current)) {
  2374. result += this._read();
  2375. }
  2376. } else if (this._current && /[a-zA-Z_$.-]/.test(this._current)) {
  2377. // suffix-id ::= ... | (letter|id-punct) (letter|id-punct|digit)*
  2378. while (this._current && /[a-zA-Z_$0-9.-]/.test(this._current)) {
  2379. if (this._current === '-' && this._peek() === '>') {
  2380. break;
  2381. }
  2382. result += this._read();
  2383. }
  2384. } else if (result.length === 1) {
  2385. const errorKinds = { '#': 'Invalid attribute name', '%': 'Invalid SSA name', '^': 'Invalid block name', '!': 'Invalid type identifier' };
  2386. throw new mlir.Error(`${errorKinds[prefix] || 'Invalid identifier'} ${this.location()}`);
  2387. }
  2388. if (prefix === '@' && this._current === ':' && this._peek() === ':') {
  2389. result += this._read();
  2390. result += this._read();
  2391. result += this.lexPrefixedIdentifier('@').getSpelling().str();
  2392. }
  2393. const kind = prefix === '$' ? '%' : prefix;
  2394. return this.formToken(kind, result);
  2395. }
  2396. formToken(kind, value) {
  2397. const token = this._tokens[this._index];
  2398. this._index = (this._index + 1) % this._tokens.length;
  2399. token.loc.position = this._position;
  2400. token.kind = kind;
  2401. token.spelling.value = value;
  2402. token.spelling.position = this._position;
  2403. return token;
  2404. }
  2405. };
  2406. _.AsmResourceParser = class {
  2407. constructor(name) {
  2408. this.name = name;
  2409. }
  2410. };
  2411. _.ParsedResourceEntry = {};
  2412. _.ParsedResourceEntry.Text = class {
  2413. constructor(key, keyLoc, value, parser) {
  2414. this.key = key;
  2415. this.keyLoc = keyLoc;
  2416. this.value = value;
  2417. this.parser = parser;
  2418. }
  2419. parseAsBool() {
  2420. if (this.value.kind === 'boolean') {
  2421. return this.value.value;
  2422. }
  2423. throw new mlir.Error(`Expected boolean value for resource entry '${this.key}'`);
  2424. }
  2425. parseAsString() {
  2426. if (this.value.kind === _.Token.string) {
  2427. return this.value.getStringValue();
  2428. }
  2429. throw new mlir.Error(`Expected string value for resource entry '${this.key}'`);
  2430. }
  2431. parseAsBlob() {
  2432. if (this.value.kind === _.Token.string) {
  2433. const hexStr = this.value.getStringValue();
  2434. if (hexStr.startsWith('0x')) {
  2435. const hex = hexStr.slice(2);
  2436. const bytes = new Uint8Array(hex.length / 2);
  2437. for (let i = 0; i < bytes.length; i++) {
  2438. bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
  2439. }
  2440. if (bytes.length >= 4) {
  2441. return bytes.slice(4);
  2442. }
  2443. return bytes;
  2444. }
  2445. }
  2446. throw new mlir.Error(`Expected hex string blob value for resource entry '${this.key}'`);
  2447. }
  2448. };
  2449. _.ParserConfig = class {
  2450. constructor(context) {
  2451. this.context = context;
  2452. this.resourceParsers = new Map();
  2453. }
  2454. getResourceParser(name) {
  2455. return this.resourceParsers.get(name);
  2456. }
  2457. attachResourceParser(parser) {
  2458. this.resourceParsers.set(parser.name, parser);
  2459. }
  2460. };
  2461. _.ParserState = class {
  2462. constructor(decoder, config) {
  2463. this.config = config;
  2464. this.defaultDialectStack = ['builtin'];
  2465. this.attributeAliasDefinitions = new Map();
  2466. this.typeAliasDefinitions = new Map();
  2467. this.dialectResources = new Map();
  2468. this.deferredLocsReferences = [];
  2469. this.lex = new _.Lexer(decoder);
  2470. this.curToken = this.lex.lexToken();
  2471. }
  2472. };
  2473. _.IsolatedSSANameScope = class {
  2474. constructor() {
  2475. this.values = new Map();
  2476. this.definitionsPerScope = [];
  2477. }
  2478. recordDefinition(def) {
  2479. this.definitionsPerScope[this.definitionsPerScope.length - 1].add(def);
  2480. }
  2481. pushSSANameScope() {
  2482. this.definitionsPerScope.push(new Set());
  2483. }
  2484. popSSANameScope() {
  2485. for (const def of this.definitionsPerScope.pop()) {
  2486. this.values.delete(def);
  2487. }
  2488. }
  2489. };
  2490. _.Parser = class {
  2491. constructor(state) {
  2492. this.state = state;
  2493. }
  2494. get context() {
  2495. return this.state.config.context;
  2496. }
  2497. parseCommaSeparatedListUntil(rightToken, parseElement, allowEmptyList = true) {
  2498. if (this.getToken().is(rightToken)) {
  2499. if (!allowEmptyList) {
  2500. throw new mlir.Error(`Expected list element ${this.location()}`);
  2501. }
  2502. this.consumeToken(rightToken);
  2503. return;
  2504. }
  2505. this.parseCommaSeparatedList('none', parseElement);
  2506. this.parseToken(rightToken, `Expected '${rightToken}'`);
  2507. }
  2508. parseResourceFileMetadata(parseBody) {
  2509. this.parseToken(_.Token.l_brace, "Expected '{'");
  2510. this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {
  2511. const nameLoc = this.getToken().loc;
  2512. const name = this.parseOptionalKeyword();
  2513. if (!name) {
  2514. throw new mlir.Error(`Expected identifier key for 'resource' entry ${this.location()}`);
  2515. }
  2516. this.parseToken(_.Token.colon);
  2517. this.parseToken(_.Token.l_brace);
  2518. parseBody(name, nameLoc);
  2519. });
  2520. }
  2521. parseDialectResourceFileMetadata() {
  2522. this.parseResourceFileMetadata((name /*, nameLoc */) => {
  2523. const dialect = this.context.getOrLoadDialect(name);
  2524. if (!dialect) {
  2525. throw new mlir.Error(`Dialect '${name}' is unknown ${this.location()}`);
  2526. }
  2527. this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {
  2528. const keyLoc = this.getToken().loc.copy();
  2529. const handle = this.parseResourceHandle(dialect);
  2530. const key = dialect.getResourceKey(handle);
  2531. this.parseToken(_.Token.colon, "Expected ':'");
  2532. const valueTok = this.getToken();
  2533. this.consumeToken();
  2534. const entry = new _.ParsedResourceEntry.Text(key, keyLoc, valueTok, this);
  2535. dialect.parseResource(entry);
  2536. });
  2537. });
  2538. }
  2539. parseExternalResourceFileMetadata() {
  2540. this.parseResourceFileMetadata((name /*, nameLoc */) => {
  2541. const handler = this.state.config.getResourceParser(name);
  2542. this.parseCommaSeparatedListUntil(_.Token.r_brace, () => {
  2543. const keyLoc = this.getToken().loc;
  2544. const key = this.parseOptionalKeywordOrString();
  2545. if (!key) {
  2546. throw new mlir.Error(`Expected identifier key for 'external_resources' entry ${this.location()}`);
  2547. }
  2548. this.parseToken(_.Token.colon, "Expected ':'");
  2549. const valueTok = this.getToken();
  2550. this.consumeToken();
  2551. if (handler && handler.parseResource) {
  2552. const entry = new _.ParsedResourceEntry.Text(key, keyLoc, valueTok, this);
  2553. handler.parseResource(entry);
  2554. }
  2555. });
  2556. });
  2557. }
  2558. parseOptionalKeywordOrString() {
  2559. const keyword = this.parseOptionalKeyword();
  2560. if (keyword) {
  2561. return keyword;
  2562. }
  2563. return this.parseOptionalString();
  2564. }
  2565. finalize(/* block */) {
  2566. }
  2567. isCurrentTokenAKeyword() {
  2568. return this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype) || this.getToken().isKeyword();
  2569. }
  2570. parseOptionalKeyword() {
  2571. if (!this.isCurrentTokenAKeyword()) {
  2572. return null;
  2573. }
  2574. const keyword = this.getTokenSpelling().str();
  2575. this.consumeToken();
  2576. return keyword;
  2577. }
  2578. parseTypeListNoParens() {
  2579. return this.parseCommaSeparatedList('none', () => this.parseType());
  2580. }
  2581. parseTypeListParens() {
  2582. this.parseToken(_.Token.l_paren, "Expected '('");
  2583. if (this.consumeIf(_.Token.r_paren)) {
  2584. return [];
  2585. }
  2586. const types = this.parseTypeListNoParens();
  2587. this.parseToken(_.Token.r_paren, "Expected ')'");
  2588. return types;
  2589. }
  2590. skip(open) {
  2591. const closingFor = { '<': '>', '[': ']', '(': ')', '{': '}' };
  2592. const openingFor = { '>': '<', ']': '[', ')': '(', '}': '{' };
  2593. const delimiters = new Set(['<', '>', '[', ']', '(', ')', '{', '}', ',', ':', '=']);
  2594. let value = '';
  2595. let prevToken = '';
  2596. if (this.getToken().is(open)) {
  2597. const stack = [open];
  2598. prevToken = this.getToken().getSpelling().str();
  2599. this.consumeToken();
  2600. value += prevToken;
  2601. while (stack.length > 0) {
  2602. if (this.getToken().is(_.Token.eof)) {
  2603. throw new mlir.Error(`Unbalanced '${stack[stack.length - 1]}' ${this.location()}`);
  2604. }
  2605. const token = this.getToken().getSpelling().str();
  2606. if (closingFor[token]) {
  2607. stack.push(token);
  2608. } else if (openingFor[token]) {
  2609. if (stack[stack.length - 1] === openingFor[token]) {
  2610. stack.pop();
  2611. } else if (token !== '>') {
  2612. throw new mlir.Error(`Unbalanced '${stack[stack.length - 1]}' ${this.location()}`);
  2613. }
  2614. }
  2615. const curToken = this.getToken().getSpelling().str();
  2616. this.consumeToken();
  2617. if (!delimiters.has(prevToken) && !delimiters.has(curToken)) {
  2618. value += ' ';
  2619. }
  2620. value += curToken;
  2621. prevToken = curToken;
  2622. }
  2623. }
  2624. return value;
  2625. }
  2626. parseSuccessors(successors) {
  2627. const parsed = this.parseCommaSeparatedList('square', () => {
  2628. const label = this.getTokenSpelling().str();
  2629. this.consumeToken(_.Token.caret_identifier);
  2630. return { label };
  2631. });
  2632. if (parsed.length === 0) {
  2633. throw new mlir.Error(`Expected at least one successor ${this.location()}`);
  2634. }
  2635. for (const s of parsed) {
  2636. successors.push(s);
  2637. }
  2638. }
  2639. parseAttributeDict(attributes) {
  2640. const seenKeys = new Set();
  2641. this.parseCommaSeparatedList('brace', () => {
  2642. // The name of an attribute can either be a bare identifier, or a string.
  2643. let name = null;
  2644. if (this.getToken().is(_.Token.string)) {
  2645. name = this.getToken().getStringValue();
  2646. } else if (this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype) || this.getToken().isKeyword()) {
  2647. name = this.getTokenSpelling().str();
  2648. } else {
  2649. throw new mlir.Error(`Expected attribute name ${this.location()}`);
  2650. }
  2651. if (!name) {
  2652. throw new mlir.Error(`Expected attribute name ${this.location()}`);
  2653. }
  2654. this.consumeToken();
  2655. if (seenKeys.has(name)) {
  2656. throw new mlir.Error(`Duplicate key '${name}' in dictionary attribute ${this.location()}`);
  2657. }
  2658. seenKeys.add(name);
  2659. if (!this.consumeIf(_.Token.equal)) {
  2660. attributes.set(name, new _.UnitAttr());
  2661. return;
  2662. }
  2663. const attr = this.parseAttribute();
  2664. attributes.set(name, attr);
  2665. });
  2666. }
  2667. parseLocationInstance() {
  2668. if (this.getToken().is(_.Token.hash_identifier)) {
  2669. const locAttr = this.parseExtendedAttr();
  2670. if (locAttr instanceof _.LocationAttr === false && locAttr instanceof _.OpaqueAttr === false) {
  2671. throw new mlir.Error(`Expected location attribute, but got '${locAttr}' ${this.location()}`);
  2672. }
  2673. return locAttr;
  2674. }
  2675. if (this.getToken().is(_.Token.string)) {
  2676. return this.parseNameOrFileLineColRange();
  2677. }
  2678. if (!this.getToken().is(_.Token.bare_identifier)) {
  2679. throw new mlir.Error(`Expected location instance, got '${this.getTokenSpelling().str()}' ${this.location()}`);
  2680. }
  2681. if (this.getToken().spelling.str() === 'callsite') {
  2682. return this.parseCallSiteLocation();
  2683. }
  2684. if (this.getToken().spelling.str() === 'fused') {
  2685. return this.parseFusedLocation();
  2686. }
  2687. if (this.getToken().spelling.str() === 'unknown') {
  2688. this.consumeToken(_.Token.bare_identifier);
  2689. return new _.UnknownLoc();
  2690. }
  2691. throw new mlir.Error(`Expected location instance, got '${this.getTokenSpelling().str()}' ${this.location()}`);
  2692. }
  2693. parseCallSiteLocation() {
  2694. this.consumeToken(_.Token.bare_identifier);
  2695. this.parseToken(_.Token.l_paren, "Expected '(' in callsite location");
  2696. const callee = this.parseLocationInstance();
  2697. if (this.getToken().isNot(_.Token.bare_identifier) || this.getToken().getSpelling().str() !== 'at') {
  2698. throw new mlir.Error(`Expected 'at' in callsite location ${this.location()}`);
  2699. }
  2700. this.consumeToken(_.Token.bare_identifier);
  2701. const caller = this.parseLocationInstance();
  2702. this.parseToken(_.Token.r_paren, "Expected ')' in callsite location");
  2703. return new _.CallSiteLoc(callee, caller);
  2704. }
  2705. parseFusedLocation() {
  2706. this.consumeToken(_.Token.bare_identifier);
  2707. let metadata = null;
  2708. if (this.consumeIf(_.Token.less)) {
  2709. metadata = this.parseAttribute();
  2710. if (!metadata) {
  2711. throw new mlir.Error(`Expected attribute in fused location metadata ${this.location()}`);
  2712. }
  2713. this.parseToken(_.Token.greater, "Expected '>' after fused location metadata");
  2714. }
  2715. const locations = this.parseCommaSeparatedList('square', () => this.parseLocationInstance());
  2716. return new _.FusedLoc(locations, metadata);
  2717. }
  2718. parseNameOrFileLineColRange() {
  2719. const str = this.getToken().getStringValue();
  2720. this.consumeToken(_.Token.string);
  2721. if (this.consumeIf(_.Token.colon)) {
  2722. if (this.getToken().isNot(_.Token.integer)) {
  2723. throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);
  2724. }
  2725. const startLine = this.getToken().getUnsignedIntegerValue();
  2726. if (startLine === null) {
  2727. throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);
  2728. }
  2729. this.consumeToken(_.Token.integer);
  2730. if (this.getToken().isNot(_.Token.colon)) {
  2731. return new _.FileLineColRange(str, startLine);
  2732. }
  2733. this.consumeToken(_.Token.colon);
  2734. if (this.getToken().isNot(_.Token.integer)) {
  2735. throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);
  2736. }
  2737. const startCol = this.getToken().getUnsignedIntegerValue();
  2738. if (startCol === null) {
  2739. throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);
  2740. }
  2741. this.consumeToken(_.Token.integer);
  2742. if (!this.isCurrentTokenAKeyword() || this.getTokenSpelling().str() !== 'to') {
  2743. return new _.FileLineColLoc(str, startLine, startCol);
  2744. }
  2745. this.consumeToken();
  2746. let endLine = null;
  2747. if (this.getToken().is(_.Token.integer)) {
  2748. endLine = this.getToken().getUnsignedIntegerValue();
  2749. if (endLine === null) {
  2750. throw new mlir.Error(`Expected integer line number in FileLineColRange ${this.location()}`);
  2751. }
  2752. this.consumeToken(_.Token.integer);
  2753. }
  2754. if (this.getToken().isNot(_.Token.colon)) {
  2755. throw new mlir.Error(`Expected either integer or ':' post 'to' in FileLineColRange ${this.location()}`);
  2756. }
  2757. this.consumeToken(_.Token.colon);
  2758. if (this.getToken().isNot(_.Token.integer)) {
  2759. throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);
  2760. }
  2761. const endCol = this.getToken().getUnsignedIntegerValue();
  2762. if (endCol === null) {
  2763. throw new mlir.Error(`Expected integer column number in FileLineColRange ${this.location()}`);
  2764. }
  2765. this.consumeToken(_.Token.integer);
  2766. if (endLine !== null) {
  2767. return new _.FileLineColRange(str, startLine, startCol, endLine, endCol);
  2768. }
  2769. return new _.FileLineColRange(str, startLine, startCol, undefined, endCol);
  2770. }
  2771. if (this.consumeIf(_.Token.l_paren)) {
  2772. const childLoc = this.parseLocationInstance();
  2773. this.parseToken(_.Token.r_paren, "Expected ')' after child location of NameLoc");
  2774. return new _.NameLoc(str, childLoc);
  2775. }
  2776. return new _.NameLoc(str);
  2777. }
  2778. parseLocationAlias() {
  2779. const tok = this.getToken();
  2780. this.consumeToken(_.Token.hash_identifier);
  2781. const identifier = tok.getSpelling().str().substring(1); // drop_front - remove '#' prefix
  2782. const attr = this.state.attributeAliasDefinitions.get(tok.getSpelling().str());
  2783. if (attr) {
  2784. if (attr instanceof _.LocationAttr) {
  2785. return attr;
  2786. }
  2787. return attr;
  2788. }
  2789. const index = this.state.deferredLocsReferences.length;
  2790. this.state.deferredLocsReferences.push({ loc: tok.loc, identifier });
  2791. return new _.OpaqueLoc(index, identifier, new _.UnknownLoc());
  2792. }
  2793. parseOptionalLocationSpecifier() {
  2794. if (!this.consumeIf(_.Token.kw_loc)) {
  2795. return null;
  2796. }
  2797. this.parseToken(_.Token.l_paren, "expected '(' in location");
  2798. const tok = this.getToken();
  2799. let directLoc = null;
  2800. if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {
  2801. directLoc = this.parseLocationAlias();
  2802. } else {
  2803. directLoc = this.parseLocationInstance();
  2804. }
  2805. this.parseToken(_.Token.r_paren, "expected ')' in location");
  2806. return directLoc;
  2807. }
  2808. parseXInDimensionList() {
  2809. // Matches ref impl: if token is 'xf32', reset lexer to after 'x'
  2810. if (this.getToken().isNot(_.Token.bare_identifier)) {
  2811. return false;
  2812. }
  2813. const token = this.getToken().getSpelling().str();
  2814. if (!token.startsWith('x')) {
  2815. return false;
  2816. }
  2817. // If we had a prefix of 'x' (e.g., 'xf32'), reset lexer to after the 'x'
  2818. if (token.length > 1) {
  2819. this.state.lex.resetPointer(this.getToken().loc.position + 1);
  2820. }
  2821. this.state.curToken = this.state.lex.lexToken();
  2822. return true;
  2823. }
  2824. parseIntegerInDimensionList() {
  2825. const spelling = this.getTokenSpelling().str();
  2826. if (spelling[0] === '0' && spelling.length > 1 && spelling[1] === 'x') {
  2827. this.state.lex.resetPointer(this.getToken().loc.position + 1);
  2828. this.state.curToken = this.state.lex.lexToken();
  2829. return 0;
  2830. }
  2831. const dimension = this.getToken().getUInt64IntegerValue();
  2832. if (dimension === null) {
  2833. throw new mlir.Error(`Invalid dimension ${this.location()}`);
  2834. }
  2835. this.consumeToken(_.Token.integer);
  2836. return dimension.toNumber();
  2837. }
  2838. parseVectorDimensionList() {
  2839. const dimensions = [];
  2840. const scalableDims = [];
  2841. while (this.getToken().is(_.Token.integer) || this.getToken().is(_.Token.l_square)) {
  2842. const scalable = this.consumeIf(_.Token.l_square);
  2843. dimensions.push(this.parseIntegerInDimensionList());
  2844. if (scalable) {
  2845. if (!this.consumeIf(_.Token.r_square)) {
  2846. throw new mlir.Error(`Missing ']' closing scalable dimension ${this.location()}`);
  2847. }
  2848. }
  2849. scalableDims.push(scalable);
  2850. if (!this.parseXInDimensionList()) {
  2851. break;
  2852. }
  2853. }
  2854. return { dimensions, scalableDims };
  2855. }
  2856. parseDimensionListRanked(allowDynamic = true, withTrailingX = true) {
  2857. const dimensions = [];
  2858. const parseDim = () => {
  2859. if (allowDynamic && this.consumeIf(_.Token.question)) {
  2860. dimensions.push(_.ShapedType.kDynamic);
  2861. return true;
  2862. }
  2863. if (this.getToken().is(_.Token.integer)) {
  2864. dimensions.push(this.parseIntegerInDimensionList());
  2865. return true;
  2866. }
  2867. return false;
  2868. };
  2869. const hasDimToken = () => this.getToken().isAny(_.Token.integer, _.Token.question);
  2870. if (withTrailingX) {
  2871. while (hasDimToken()) {
  2872. if (!parseDim() || !this.parseXInDimensionList()) {
  2873. break;
  2874. }
  2875. }
  2876. } else if (parseDim()) {
  2877. while (this.getToken().is(_.Token.bare_identifier) && this.getTokenSpelling().str().startsWith('x')) {
  2878. if (!this.parseXInDimensionList() || !parseDim()) {
  2879. break;
  2880. }
  2881. }
  2882. }
  2883. return { dimensions };
  2884. }
  2885. parseTensorType() {
  2886. this.parseToken(_.Token.less, "Expected '<' in tensor type");
  2887. let isUnranked = false;
  2888. let dimensions = [];
  2889. if (this.consumeIf(_.Token.star)) {
  2890. isUnranked = true;
  2891. this.parseXInDimensionList();
  2892. } else {
  2893. const dimInfo = this.parseDimensionListRanked();
  2894. dimensions = dimInfo.dimensions;
  2895. }
  2896. const elementType = this.parseType();
  2897. let encoding = null;
  2898. if (this.consumeIf(_.Token.comma)) {
  2899. encoding = this.parseAttribute();
  2900. }
  2901. this.parseToken(_.Token.greater, "Expected '>' in tensor type");
  2902. if (elementType instanceof _.NoneType || elementType instanceof _.FunctionType ||
  2903. elementType instanceof _.TupleType || elementType instanceof _.RankedTensorType ||
  2904. elementType instanceof _.UnrankedTensorType || elementType instanceof _.MemRefType ||
  2905. elementType instanceof _.UnrankedMemRefType) {
  2906. throw new mlir.Error(`Invalid tensor element type ${this.location()}`);
  2907. }
  2908. if (isUnranked) {
  2909. if (encoding) {
  2910. throw new mlir.Error(`Cannot apply encoding to unranked tensor ${this.location()}`);
  2911. }
  2912. return new _.UnrankedTensorType(elementType);
  2913. }
  2914. return new _.RankedTensorType(dimensions, elementType, encoding);
  2915. }
  2916. parseMemRefType() {
  2917. this.parseToken(_.Token.less, "Expected '<' in memref type");
  2918. let isUnranked = false;
  2919. let dimensions = [];
  2920. if (this.consumeIf(_.Token.star)) {
  2921. isUnranked = true;
  2922. this.parseXInDimensionList();
  2923. } else {
  2924. const dimInfo = this.parseDimensionListRanked();
  2925. dimensions = dimInfo.dimensions;
  2926. }
  2927. const elementType = this.parseType();
  2928. if (elementType instanceof _.NoneType || elementType instanceof _.FunctionType ||
  2929. elementType instanceof _.TupleType || elementType instanceof _.RankedTensorType ||
  2930. elementType instanceof _.UnrankedTensorType) {
  2931. throw new mlir.Error(`Invalid memref element type ${this.location()}`);
  2932. }
  2933. let layout = null;
  2934. let memorySpace = null;
  2935. while (this.consumeIf(_.Token.comma)) {
  2936. const attr = this.parseAttribute();
  2937. const isLayout = attr instanceof _.AffineMapAttr || (attr && attr.type === 'strided') || (attr instanceof _.OpaqueAttr && attr.toString().includes('layout'));
  2938. if (isLayout) {
  2939. layout = attr;
  2940. if (isUnranked) {
  2941. throw new mlir.Error(`Cannot have affine map for unranked memref type ${this.location()}`);
  2942. }
  2943. if (memorySpace) {
  2944. throw new mlir.Error(`Expected memory space to be last in memref type ${this.location()}`);
  2945. }
  2946. } else {
  2947. if (memorySpace) {
  2948. throw new mlir.Error(`Multiple memory spaces specified in memref type ${this.location()}`);
  2949. }
  2950. memorySpace = attr;
  2951. }
  2952. }
  2953. this.parseToken(_.Token.greater, "Expected '>' in memref type");
  2954. if (isUnranked) {
  2955. return new _.UnrankedMemRefType(elementType, memorySpace);
  2956. }
  2957. return new _.MemRefType(dimensions, elementType, layout, memorySpace);
  2958. }
  2959. parseVectorType() {
  2960. this.parseToken(_.Token.less, "Expected '<' in vector type");
  2961. const dimInfo = this.parseVectorDimensionList();
  2962. const elementType = this.parseType();
  2963. this.parseToken(_.Token.greater, "Expected '>' in vector type");
  2964. return new _.VectorType(dimInfo.dimensions, elementType, dimInfo.scalableDims);
  2965. }
  2966. parseComplexType() {
  2967. this.parseToken(_.Token.less, "Expected '<' in complex type");
  2968. const elementType = this.parseType();
  2969. if (!(elementType instanceof _.FloatType) && !(elementType instanceof _.IntegerType)) {
  2970. throw new mlir.Error(`Invalid element type for complex ${this.location()}`);
  2971. }
  2972. this.parseToken(_.Token.greater, "Expected '>' in complex type");
  2973. return new _.ComplexType(elementType);
  2974. }
  2975. parseTupleType() {
  2976. this.parseToken(_.Token.less, "Expected '<' in tuple type");
  2977. if (this.consumeIf(_.Token.greater)) {
  2978. return new _.TupleType([]);
  2979. }
  2980. const types = this.parseCommaSeparatedList('none', () => this.parseType());
  2981. this.parseToken(_.Token.greater, "Expected '>' in tuple type");
  2982. return new _.TupleType(types);
  2983. }
  2984. parseCustomTypeWithFallback(typeT) {
  2985. if (typeT && this.getToken().isNot(_.Token.exclamation_identifier)) {
  2986. if (typeof typeT === 'function') {
  2987. return typeT(this);
  2988. }
  2989. const index = typeT.name.indexOf('.');
  2990. if (index === -1) {
  2991. throw new mlir.Error(`Invalid type name '${typeT.name}.`);
  2992. }
  2993. const dialectName = typeT.name.substring(0, index);
  2994. const dialect = this.context.getOrLoadDialect(dialectName);
  2995. this.context.checkDialect(dialect, dialectName, 'custom type');
  2996. return dialect.parseCustomTypeWithFallback(this, typeT.type);
  2997. }
  2998. return this.parseType();
  2999. }
  3000. parseCustomAttributeWithFallback(attrT, type) {
  3001. if (attrT) {
  3002. return attrT(this, type);
  3003. }
  3004. return this.parseAttribute(type);
  3005. }
  3006. parseType() {
  3007. if (this.getToken().is(_.Token.l_paren)) {
  3008. return this.parseFunctionType();
  3009. }
  3010. return this.parseNonFunctionType();
  3011. }
  3012. parseOptionalType() {
  3013. switch (this.getToken().kind) {
  3014. case _.Token.l_paren:
  3015. case _.Token.exclamation_identifier:
  3016. case _.Token.inttype:
  3017. return this.parseType();
  3018. case _.Token.bare_identifier: {
  3019. switch (this.getToken().getSpelling().str()) {
  3020. case 'memref':
  3021. case 'tensor':
  3022. case 'complex':
  3023. case 'tuple':
  3024. case 'vector':
  3025. case 'f4E2M1FN':
  3026. case 'f6E2M3FN':
  3027. case 'f6E3M2FN':
  3028. case 'f8E5M2':
  3029. case 'f8E4M3':
  3030. case 'f8E4M3FN':
  3031. case 'f8E5M2FNUZ':
  3032. case 'f8E4M3FNUZ':
  3033. case 'f8E4M3B11FNUZ':
  3034. case 'f8E3M4':
  3035. case 'f8E8M0FNU':
  3036. case 'bf16':
  3037. case 'f16':
  3038. case 'tf32':
  3039. case 'f32':
  3040. case 'f64':
  3041. case 'f80':
  3042. case 'f128':
  3043. case 'index':
  3044. case 'none':
  3045. return this.parseType();
  3046. default:
  3047. break;
  3048. }
  3049. break;
  3050. }
  3051. default: {
  3052. break;
  3053. }
  3054. }
  3055. return null;
  3056. }
  3057. parseNonFunctionType() {
  3058. switch (this.getToken().kind) {
  3059. case _.Token.inttype: {
  3060. const width = this.getToken().getIntTypeBitwidth();
  3061. if (width === null) {
  3062. throw new mlir.Error(`Invalid integer width ${this.location()}`);
  3063. }
  3064. if (width > _.IntegerType.kMaxWidth) {
  3065. throw new mlir.Error(`Integer bitwidth is limited to ${_.IntegerType.kMaxWidth} bits ${this.location()}`);
  3066. }
  3067. const signedness = this.getToken().getIntTypeSignedness();
  3068. this.consumeToken(_.Token.inttype);
  3069. let prefix = 'i';
  3070. if (signedness === true) {
  3071. prefix = 'si';
  3072. } else if (signedness === false) {
  3073. prefix = 'ui';
  3074. }
  3075. return new _.IntegerType(`${prefix}${width}`);
  3076. }
  3077. case _.Token.exclamation_identifier: {
  3078. return this.parseExtendedType();
  3079. }
  3080. case _.Token.bare_identifier: {
  3081. const value = this.getTokenSpelling().str();
  3082. this.consumeToken(_.Token.bare_identifier);
  3083. switch (value) {
  3084. case 'tensor':
  3085. return this.parseTensorType();
  3086. case 'vector':
  3087. return this.parseVectorType();
  3088. case 'memref':
  3089. return this.parseMemRefType();
  3090. case 'complex':
  3091. return this.parseComplexType();
  3092. case 'tuple':
  3093. return this.parseTupleType();
  3094. case 'none':
  3095. return new _.NoneType();
  3096. case 'index':
  3097. return new _.IndexType();
  3098. case 'bf16':
  3099. case 'f16':
  3100. case 'f32':
  3101. case 'f64':
  3102. case 'f80':
  3103. case 'f128':
  3104. case 'tf32':
  3105. case 'f8E5M2':
  3106. case 'f8E4M3':
  3107. case 'f8E4M3FN':
  3108. case 'f8E5M2FNUZ':
  3109. case 'f8E4M3FNUZ':
  3110. case 'f8E4M3B11FNUZ':
  3111. case 'f8E3M4':
  3112. case 'f8E8M0FNU':
  3113. case 'f4E2M1FN':
  3114. case 'f6E2M3FN':
  3115. case 'f6E3M2FN':
  3116. return new _.FloatType(value);
  3117. default:
  3118. throw new mlir.Error(`Invalid type '${value}' ${this.location()}`);
  3119. }
  3120. }
  3121. default: {
  3122. break;
  3123. }
  3124. }
  3125. throw new mlir.Error(`Invalid type '${this.getTokenSpelling().str()}' ${this.location()}`);
  3126. }
  3127. parseExtendedType() {
  3128. return this.parseExtendedSymbol(this.state.asmState, this.state.typeAliasDefinitions, (dialectName, symbolData) => {
  3129. const dialect = this.context.getOrLoadDialect(dialectName);
  3130. if (dialect) {
  3131. const curLexerPos = this.getToken().loc.position;
  3132. this.resetToken(symbolData.data());
  3133. const customParser = new _.CustomDialectAsmParser(symbolData, this);
  3134. const type = dialect.parseType(customParser, dialectName);
  3135. this.resetToken(curLexerPos);
  3136. return type;
  3137. }
  3138. return new _.OpaqueType(dialectName, symbolData);
  3139. });
  3140. }
  3141. parseExtendedSymbol(asmState, aliases, createSymbol) {
  3142. const tok = this.getToken();
  3143. const startPos = tok.loc.position;
  3144. const tokSpelling = tok.getSpelling().str();
  3145. const isType = tokSpelling.startsWith('!');
  3146. const identifier = tok.getSpelling().drop_front();
  3147. this.consumeToken();
  3148. const dotIndex = identifier.indexOf('.');
  3149. let dialectName = identifier;
  3150. let symbolData = '';
  3151. if (dotIndex !== -1) {
  3152. dialectName = identifier.substring(0, dotIndex);
  3153. symbolData = identifier.substring(dotIndex + 1);
  3154. }
  3155. const isPrettyName = symbolData.length > 0;
  3156. const hasTrailingData = this.getToken().is(_.Token.less);
  3157. if (!hasTrailingData && !isPrettyName) {
  3158. if (!aliases.has(tokSpelling)) {
  3159. throw new mlir.Error(`Undefined symbol alias '${identifier}' ${this.location()}`);
  3160. }
  3161. if (asmState) {
  3162. if (isType) {
  3163. asmState.addTypeAliasUses(identifier);
  3164. } else {
  3165. asmState.addAttrAliasUses(identifier);
  3166. }
  3167. }
  3168. return aliases.get(tokSpelling);
  3169. }
  3170. if (hasTrailingData) {
  3171. if (this.getToken().is(_.Token.less)) {
  3172. symbolData += this.skip(_.Token.less);
  3173. } else if (this.getToken().is(_.Token.l_paren)) {
  3174. symbolData += this.skip(_.Token.l_paren);
  3175. }
  3176. if (!isPrettyName) {
  3177. symbolData = symbolData.slice(1, -1);
  3178. }
  3179. }
  3180. const posOffset = dotIndex === -1 ? dialectName.length : dotIndex;
  3181. symbolData = new _.StringRef(symbolData, startPos + 1 + posOffset + 1);
  3182. return createSymbol(dialectName, symbolData);
  3183. }
  3184. parseFunctionType() {
  3185. const inputs = this.parseTypeListParens();
  3186. this.parseToken(_.Token.arrow, "Expected '->' in function type");
  3187. const results = this.parseFunctionResultTypes();
  3188. return new _.FunctionType(inputs, results);
  3189. }
  3190. parseFunctionResultTypes() {
  3191. if (this.getToken().is(_.Token.l_paren)) {
  3192. return this.parseTypeListParens();
  3193. }
  3194. const type = this.parseNonFunctionType();
  3195. if (type) {
  3196. return [type];
  3197. }
  3198. return [];
  3199. }
  3200. parseCommaSeparatedList(delimiter, parseElement) {
  3201. const results = [];
  3202. const delimiters = {
  3203. none: [null, null],
  3204. paren: [_.Token.l_paren, _.Token.r_paren],
  3205. square: [_.Token.l_square, _.Token.r_square],
  3206. angle: [_.Token.less, _.Token.greater],
  3207. brace: [_.Token.l_brace, _.Token.r_brace],
  3208. optionalParen: [_.Token.l_paren, _.Token.r_paren],
  3209. optionalSquare: [_.Token.l_square, _.Token.r_square],
  3210. optionalAngle: [_.Token.less, _.Token.greater],
  3211. optionalBrace: [_.Token.l_brace, _.Token.r_brace]
  3212. };
  3213. const [open, close] = delimiters[delimiter] || [null, null];
  3214. const isOptional = delimiter && delimiter.startsWith('optional');
  3215. if (open) {
  3216. if (isOptional) {
  3217. if (!this.consumeIf(open)) {
  3218. return results;
  3219. }
  3220. } else {
  3221. this.parseToken(open, `Expected '${open}'`);
  3222. }
  3223. if (close && this.consumeIf(close)) {
  3224. return results;
  3225. }
  3226. }
  3227. const first = parseElement();
  3228. if (first !== null && first !== undefined) {
  3229. results.push(first);
  3230. }
  3231. while (this.consumeIf(_.Token.comma)) {
  3232. const elem = parseElement();
  3233. if (elem !== null && elem !== undefined) {
  3234. results.push(elem);
  3235. }
  3236. }
  3237. if (close) {
  3238. this.parseToken(close, `Expected '${close}'`);
  3239. }
  3240. return results;
  3241. }
  3242. parseFloatAttr(type = null, isNegative = false) {
  3243. const val = this.getToken().getFloatingPointValue();
  3244. if (val === null) {
  3245. throw new mlir.Error(`Floating point value too large for attribute ${this.location()}`);
  3246. }
  3247. this.consumeToken(_.Token.floatliteral);
  3248. if (!type) {
  3249. if (this.consumeIf(_.Token.colon)) {
  3250. type = this.parseType();
  3251. } else {
  3252. type = new _.FloatType('f64');
  3253. }
  3254. }
  3255. if (type instanceof _.FloatType === false) {
  3256. throw new mlir.Error(`Floating point value not valid for specified type ${this.location()}`);
  3257. }
  3258. return new _.FloatAttr(type, isNegative ? -val : val);
  3259. }
  3260. parseDecOrHexAttr(type = null, isNegative = false) {
  3261. const tok = this.getToken();
  3262. const spelling = tok.getSpelling().str();
  3263. this.consumeToken(_.Token.integer);
  3264. if (!type) {
  3265. if (this.consumeIf(_.Token.colon)) {
  3266. type = this.parseType();
  3267. } else {
  3268. type = new _.IntegerType('i64');
  3269. }
  3270. }
  3271. if (type instanceof _.FloatType) {
  3272. return new _.FloatAttr(type, isNegative ? -spelling : spelling);
  3273. }
  3274. if (!(type instanceof _.IntegerType) && !(type instanceof _.IndexType)) {
  3275. throw new mlir.Error(`Integer literal not valid for specified type ${this.location()}`);
  3276. }
  3277. if (isNegative && type instanceof _.IntegerType && type.name.startsWith('ui')) {
  3278. throw new mlir.Error(`Negative integer literal not valid for unsigned integer type ${this.location()}`);
  3279. }
  3280. const val = tok.spelling.getAsInteger(spelling.length > 1 && spelling[1] === 'x' ? 0 : 10);
  3281. if (val === null) {
  3282. throw new mlir.Error(`Integer constant out of range for attribute ${this.location()}`);
  3283. }
  3284. return new _.IntegerAttr(type, isNegative ? -val : val);
  3285. }
  3286. parseAttribute(type = null) {
  3287. switch (this.getToken().kind) {
  3288. case _.Token.kw_affine_map: {
  3289. this.consumeToken(_.Token.kw_affine_map);
  3290. this.parseToken(_.Token.less, "Expected '<' in affine map");
  3291. const map = this.parseAffineMapReference();
  3292. this.parseToken(_.Token.greater, "Expected '>' in affine map");
  3293. return new _.AffineMapAttr(map);
  3294. }
  3295. case _.Token.kw_affine_set: {
  3296. this.consumeToken(_.Token.kw_affine_set);
  3297. this.parseToken(_.Token.less, "Expected '<' in integer set");
  3298. const set = this.parseIntegerSetReference();
  3299. this.parseToken(_.Token.greater, "Expected '>' in integer set");
  3300. return new _.IntegerSetAttr(set);
  3301. }
  3302. case _.Token.l_square: {
  3303. this.consumeToken(_.Token.l_square);
  3304. const elements = [];
  3305. this.parseCommaSeparatedListUntil(_.Token.r_square, () => {
  3306. elements.push(this.parseAttribute());
  3307. });
  3308. return new _.ArrayAttr(elements);
  3309. }
  3310. case _.Token.kw_false:
  3311. this.consumeToken(_.Token.kw_false);
  3312. return new _.BoolAttr(false);
  3313. case _.Token.kw_true:
  3314. this.consumeToken(_.Token.kw_true);
  3315. return new _.BoolAttr(true);
  3316. case _.Token.kw_dense:
  3317. return this.parseDenseElementsAttr(type);
  3318. case _.Token.kw_dense_resource:
  3319. return this.parseDenseResourceElementsAttr(type);
  3320. case _.Token.kw_array:
  3321. return this.parseDenseArrayAttr(type);
  3322. case _.Token.l_brace: {
  3323. const attributes = new Map();
  3324. this.parseAttributeDict(attributes);
  3325. return new _.DictionaryAttr(attributes);
  3326. }
  3327. case _.Token.hash_identifier:
  3328. return this.parseExtendedAttr(type);
  3329. case _.Token.floatliteral:
  3330. return this.parseFloatAttr(type, false);
  3331. case _.Token.integer:
  3332. return this.parseDecOrHexAttr(type, false);
  3333. case _.Token.minus: {
  3334. this.consumeToken(_.Token.minus);
  3335. if (this.getToken().is(_.Token.integer)) {
  3336. return this.parseDecOrHexAttr(type, true);
  3337. }
  3338. if (this.getToken().is(_.Token.floatliteral)) {
  3339. return this.parseFloatAttr(type, true);
  3340. }
  3341. throw new mlir.Error(`Expected constant integer or floating point value ${this.location()}`);
  3342. }
  3343. case _.Token.kw_loc:
  3344. return this.parseOptionalLocationSpecifier();
  3345. case _.Token.kw_sparse:
  3346. return this.parseSparseElementsAttr(type);
  3347. case _.Token.kw_strided:
  3348. return this.parseStridedLayoutAttr();
  3349. case _.Token.kw_distinct:
  3350. return this.parseDistinctAttr(type);
  3351. case _.Token.string: {
  3352. const value = this.getToken().getStringValue();
  3353. this.consumeToken(_.Token.string);
  3354. if (!type && this.consumeIf(_.Token.colon)) {
  3355. type = this.parseType();
  3356. }
  3357. return new _.StringAttr(value, type);
  3358. }
  3359. case _.Token.at_identifier: {
  3360. const nameStr = this.getToken().getSymbolReference();
  3361. this.consumeToken(_.Token.at_identifier);
  3362. const nestedRefs = [];
  3363. while (this.getToken().is(_.Token.colon)) {
  3364. const curPointer = this.getToken().loc.position;
  3365. this.consumeToken(_.Token.colon);
  3366. if (!this.consumeIf(_.Token.colon)) {
  3367. this.resetToken(curPointer);
  3368. break;
  3369. }
  3370. if (this.getToken().isNot(_.Token.at_identifier)) {
  3371. throw new mlir.Error(`Expected nested symbol reference identifier ${this.location()}`);
  3372. }
  3373. nestedRefs.push(this.getToken().getSymbolReference());
  3374. this.consumeToken(_.Token.at_identifier);
  3375. }
  3376. return new _.SymbolRefAttr(nameStr, nestedRefs);
  3377. }
  3378. case _.Token.kw_unit:
  3379. this.consumeToken(_.Token.kw_unit);
  3380. return new _.UnitAttr();
  3381. case _.Token.bare_identifier: {
  3382. const tokenValue = this.getTokenSpelling().str();
  3383. if (tokenValue === 'tensor' || tokenValue === 'vector' || tokenValue === 'memref' ||
  3384. tokenValue === 'none' || tokenValue === 'index' || /^[su]?i[0-9]+$/.test(tokenValue) ||
  3385. /^f[0-9]+$/.test(tokenValue) || tokenValue === 'bf16' || tokenValue === 'tf32' ||
  3386. /^f\d+E\d+M\d+/.test(tokenValue) || tokenValue === 'complex' || tokenValue === 'tuple') {
  3387. const parsedType = this.parseType();
  3388. return { value: parsedType, type: new _.PrimitiveType('type') };
  3389. }
  3390. if (tokenValue === 'DEFAULT') {
  3391. this.consumeToken(_.Token.bare_identifier);
  3392. return { value: tokenValue };
  3393. }
  3394. this.consumeToken(_.Token.bare_identifier);
  3395. if (this.getToken().is(_.Token.less)) {
  3396. return { value: tokenValue + this.skip('<') };
  3397. }
  3398. return { value: tokenValue };
  3399. }
  3400. case _.Token.exclamation_identifier: {
  3401. const parsedType = this.parseType();
  3402. return { value: parsedType, type: new _.PrimitiveType('type') };
  3403. }
  3404. case _.Token.percent_identifier: {
  3405. const value = this.getTokenSpelling().str();
  3406. this.consumeToken(_.Token.percent_identifier);
  3407. return { value };
  3408. }
  3409. case _.Token.less: {
  3410. const value = this.skip('<');
  3411. return { value };
  3412. }
  3413. default: {
  3414. const parsedType = this.parseOptionalType();
  3415. if (parsedType) {
  3416. return new _.TypeAttrOf(parsedType);
  3417. }
  3418. throw new mlir.Error(`Unexpected attribute token '${this.getTokenSpelling().str()}' ${this.location()}`);
  3419. }
  3420. }
  3421. }
  3422. parseExtendedAttr(type = null) {
  3423. const attr = this.parseExtendedSymbol(this.state.asmState, this.state.attributeAliasDefinitions, (dialectName, symbolData) => {
  3424. let attrType = type;
  3425. if (this.consumeIf(_.Token.colon)) {
  3426. attrType = this.parseType();
  3427. if (!attrType) {
  3428. return new _.Attribute();
  3429. }
  3430. }
  3431. const dialect = this.context.getOrLoadDialect(dialectName);
  3432. if (dialect) {
  3433. const curLexerPos = this.getToken().loc.position;
  3434. this.resetToken(symbolData.data());
  3435. const customParser = new _.CustomDialectAsmParser(symbolData, this);
  3436. const attr = dialect.parseAttribute(customParser, attrType);
  3437. this.resetToken(curLexerPos);
  3438. if (attr) {
  3439. return attr;
  3440. }
  3441. }
  3442. return new _.OpaqueAttr(`#${dialectName}`, symbolData, attrType);
  3443. });
  3444. return attr;
  3445. }
  3446. parseResourceHandle(dialect) {
  3447. const name = this.parseOptionalKeywordOrString();
  3448. if (!name) {
  3449. throw new mlir.Error(`Expected identifier key for 'resource' entry ${this.location()}`);
  3450. }
  3451. const resources = this.state.dialectResources;
  3452. if (!resources.has(dialect)) {
  3453. resources.set(dialect, new Map());
  3454. }
  3455. const dialectEntries = resources.get(dialect);
  3456. if (!dialectEntries.has(name)) {
  3457. const handle = dialect.declareResource(name);
  3458. const key = dialect.getResourceKey(handle);
  3459. dialectEntries.set(name, { key, handle });
  3460. }
  3461. const entry = dialectEntries.get(name);
  3462. return entry.handle;
  3463. }
  3464. parseDenseElementsAttr(attrType) {
  3465. this.consumeToken(_.Token.kw_dense);
  3466. this.parseToken(_.Token.less, "Expected '<' after 'dense'");
  3467. let literalParser = null;
  3468. if (!this.consumeIf(_.Token.greater)) {
  3469. literalParser = new _.TensorLiteralParser(this);
  3470. literalParser.parse(/* allowHex */ true);
  3471. this.parseToken(_.Token.greater, "Expected '>'");
  3472. }
  3473. const type = this.parseElementsLiteralType(attrType);
  3474. const value = literalParser ? literalParser.getAttr(type) : null;
  3475. return new _.DenseElementsAttr(value, type);
  3476. }
  3477. parseDenseResourceElementsAttr(attrType) {
  3478. this.consumeToken(_.Token.kw_dense_resource);
  3479. this.parseToken(_.Token.less, "Expected '<' after 'dense_resource'");
  3480. const rawHandle = this.parseResourceHandle(this.context.getOrLoadDialect('builtin'));
  3481. this.parseToken(_.Token.greater, "Expected '>'");
  3482. let type = attrType;
  3483. if (!type) {
  3484. this.parseToken(_.Token.colon, "Expected ':'");
  3485. type = this.parseType();
  3486. }
  3487. return new _.DenseResourceElementsAttr(type, rawHandle);
  3488. }
  3489. parseDenseArrayAttr(/* attrType */) {
  3490. this.consumeToken(_.Token.kw_array);
  3491. this.parseToken(_.Token.less, "Expected '<' after 'array'");
  3492. const arrayType = this.parseType();
  3493. if (!(arrayType instanceof _.IntegerType) && !(arrayType instanceof _.FloatType)) {
  3494. throw new mlir.Error(`Expected integer or float type, got '${arrayType}' ${this.location()}`);
  3495. }
  3496. if (this.consumeIf(_.Token.greater)) {
  3497. return new _.DenseArrayAttr(arrayType, 0, []);
  3498. }
  3499. const arrayValues = [];
  3500. if (this.consumeIf(_.Token.colon)) {
  3501. while (this.getToken().isNot(_.Token.greater)) {
  3502. const val = this.parseAttribute();
  3503. arrayValues.push(val && val.value !== undefined ? val.value : val);
  3504. this.consumeIf(_.Token.comma);
  3505. }
  3506. }
  3507. this.parseToken(_.Token.greater, "Expected '>' to close an array attribute");
  3508. return new _.DenseArrayAttr(arrayType, arrayValues.length, arrayValues);
  3509. }
  3510. parseSparseElementsAttr(attrType) {
  3511. this.consumeToken(_.Token.kw_sparse);
  3512. this.parseToken(_.Token.less, "Expected '<' after 'sparse'");
  3513. let indices = null;
  3514. let values = null;
  3515. if (!this.consumeIf(_.Token.greater)) {
  3516. const indiceParser = new _.TensorLiteralParser(this);
  3517. indiceParser.parse(/* allowHex */ false);
  3518. indices = indiceParser._storage.map((elem) => {
  3519. const val = elem.isNegative ? -elem.value : elem.value;
  3520. return typeof val === 'string' ? parseInt(val, 10) : val;
  3521. });
  3522. this.parseToken(_.Token.comma, "Expected ','");
  3523. const valuesParser = new _.TensorLiteralParser(this);
  3524. valuesParser.parse(/* allowHex */ true);
  3525. if (valuesParser._hexStorage) {
  3526. values = valuesParser._hexStorage;
  3527. } else {
  3528. values = valuesParser._storage.map((elem) => {
  3529. if (elem.kind === 'float') {
  3530. const val = parseFloat(elem.value);
  3531. return elem.isNegative ? -val : val;
  3532. }
  3533. const val = elem.isNegative ? -elem.value : elem.value;
  3534. return typeof val === 'string' ? parseFloat(val) : val;
  3535. });
  3536. }
  3537. this.parseToken(_.Token.greater, "Expected '>'");
  3538. }
  3539. const type = this.parseElementsLiteralType(attrType);
  3540. return new _.SparseElementsAttr(type, indices, values);
  3541. }
  3542. parseStridedLayoutAttr() {
  3543. this.consumeToken(_.Token.kw_strided);
  3544. this.parseToken(_.Token.less, "Expected '<' after 'strided'");
  3545. this.parseToken(_.Token.l_square, "Expected '['");
  3546. // Parse dimension list: integer or '?' separated by commas
  3547. const strides = [];
  3548. while (this.getToken().isNot(_.Token.r_square)) {
  3549. const value = this.parseOptionalInteger();
  3550. if (value !== null) {
  3551. strides.push(value);
  3552. } else if (this.consumeIf(_.Token.question)) {
  3553. strides.push('?');
  3554. } else {
  3555. throw new mlir.Error(`Expected a 64-bit signed integer or '?' in strided layout ${this.location()}`);
  3556. }
  3557. if (this.getToken().isNot(_.Token.r_square)) {
  3558. this.consumeIf(_.Token.comma);
  3559. }
  3560. }
  3561. this.parseToken(_.Token.r_square, "Expected ']'");
  3562. let offset = null;
  3563. if (this.consumeIf(_.Token.comma)) {
  3564. this.parseToken(_.Token.kw_offset, "Expected 'offset' after comma");
  3565. this.parseToken(_.Token.colon, "Expected ':' after 'offset'");
  3566. offset = this.parseOptionalInteger();
  3567. if (offset === null) {
  3568. if (this.consumeIf(_.Token.question)) {
  3569. offset = '?';
  3570. } else {
  3571. throw new mlir.Error(`Expected a 64-bit signed integer or '?' for offset in strided layout ${this.location()}`);
  3572. }
  3573. }
  3574. }
  3575. this.parseToken(_.Token.greater, "Expected '>'");
  3576. const stridesStr = `[${strides.join(', ')}]`;
  3577. const offsetStr = offset === null ? '' : `, offset: ${offset}`;
  3578. return { value: `strided<${stridesStr}${offsetStr}>`, type: 'strided', strides, offset };
  3579. }
  3580. // Parse an affine map reference using AffineParser
  3581. // Following reference: Parser::parseAffineMapReference
  3582. parseAffineMapReference() {
  3583. const affineParser = new _.AffineParser(this.state);
  3584. const result = affineParser.parseAffineMapOrIntegerSetInline();
  3585. if (result.set) {
  3586. throw new mlir.Error(`Expected AffineMap, but got IntegerSet ${this.location()}`);
  3587. }
  3588. return result.map;
  3589. }
  3590. // Parse an integer set reference using AffineParser
  3591. // Following reference: Parser::parseIntegerSetReference
  3592. parseIntegerSetReference() {
  3593. const affineParser = new _.AffineParser(this.state);
  3594. const result = affineParser.parseAffineMapOrIntegerSetInline();
  3595. if (result.map) {
  3596. throw new mlir.Error(`Expected IntegerSet, but got AffineMap ${this.location()}`);
  3597. }
  3598. return result.set;
  3599. }
  3600. // Parse an AffineMap where dims/symbols are SSA ids
  3601. // Following reference: Parser::parseAffineMapOfSSAIds
  3602. parseAffineMapOfSSAIds(parseElement, delimiter = 'Paren') {
  3603. const affineParser = new _.AffineParser(this.state, true, parseElement);
  3604. return affineParser.parseAffineMapOfSSAIds(delimiter);
  3605. }
  3606. // Parse an AffineExpr where dims/symbols are SSA ids
  3607. // Following reference: Parser::parseAffineExprOfSSAIds
  3608. parseAffineExprOfSSAIds(parseElement) {
  3609. const affineParser = new _.AffineParser(this.state, true, parseElement);
  3610. return affineParser.parseAffineExprOfSSAIds();
  3611. }
  3612. parseDistinctAttr(type) {
  3613. this.consumeToken(_.Token.kw_distinct);
  3614. this.parseToken(_.Token.l_square, "Expected '[' after 'distinct'");
  3615. if (this.getToken().isNot(_.Token.integer)) {
  3616. throw new mlir.Error(`Expected distinct ID ${this.location()}`);
  3617. }
  3618. const token = this.getToken();
  3619. const id = token.getUInt64IntegerValue();
  3620. if (id === null) {
  3621. throw new mlir.Error(`Expected an unsigned 64-bit integer ${this.location()}`);
  3622. }
  3623. this.consumeToken(_.Token.integer);
  3624. this.parseToken(_.Token.r_square, "Expected ']' to close distinct ID");
  3625. this.parseToken(_.Token.less, "Expected '<' after distinct ID");
  3626. let referencedAttr = null;
  3627. if (this.consumeIf(_.Token.greater)) {
  3628. referencedAttr = new _.UnitAttr();
  3629. } else {
  3630. referencedAttr = this.parseAttribute(type);
  3631. this.parseToken(_.Token.greater, "Expected '>' to close distinct attribute");
  3632. }
  3633. return { value: `distinct[${id.toString()}]`, referencedAttr, type: 'distinct' };
  3634. }
  3635. parseElementsLiteralType(type) {
  3636. if (!type) {
  3637. this.parseToken(_.Token.colon, "Expected ':'");
  3638. return this.parseType();
  3639. }
  3640. // Type is a concrete type object - use it directly
  3641. return type;
  3642. }
  3643. parseOptionalAttribute(type) {
  3644. switch (this.getToken().kind) {
  3645. case _.Token.at_identifier:
  3646. case _.Token.percent_identifier:
  3647. case _.Token.integer:
  3648. case _.Token.floatliteral:
  3649. case _.Token.hash_identifier:
  3650. case _.Token.l_square:
  3651. case _.Token.l_brace:
  3652. case _.Token.less:
  3653. case _.Token.string:
  3654. return this.parseAttribute(type);
  3655. case _.Token.minus:
  3656. case _.Token.kw_loc:
  3657. case _.Token.kw_affine_map:
  3658. case _.Token.kw_affine_set:
  3659. case _.Token.kw_dense:
  3660. case _.Token.kw_dense_resource:
  3661. case _.Token.kw_array:
  3662. case _.Token.kw_sparse:
  3663. case _.Token.kw_strided:
  3664. case _.Token.kw_distinct:
  3665. case _.Token.kw_unit:
  3666. case _.Token.kw_true:
  3667. case _.Token.kw_false:
  3668. return this.parseAttribute(type);
  3669. default: {
  3670. const value = this.parseOptionalType(type);
  3671. if (value) {
  3672. return { value, type: 'type' };
  3673. }
  3674. return null;
  3675. }
  3676. }
  3677. }
  3678. parseOptionalInteger() {
  3679. // Parse `false` and `true` keywords as 0 and 1 respectively.
  3680. if (this.consumeIf(_.Token.kw_false)) {
  3681. return 0;
  3682. }
  3683. if (this.consumeIf(_.Token.kw_true)) {
  3684. return 1;
  3685. }
  3686. if (this.getToken().isNot(_.Token.integer) && this.getToken().isNot(_.Token.minus)) {
  3687. return null;
  3688. }
  3689. const negative = this.consumeIf(_.Token.minus);
  3690. const curTok = this.getToken();
  3691. this.parseToken(_.Token.integer, 'Expected integer value');
  3692. const spelling = curTok.spelling;
  3693. const isHex = spelling.length > 1 && spelling[1] === 'x';
  3694. const result = spelling.getAsInteger(isHex ? 0 : 10);
  3695. if (result === null) {
  3696. throw new mlir.Error(`Integer value too large ${this.location()}`);
  3697. }
  3698. return negative ? -result : result;
  3699. }
  3700. parseInteger() {
  3701. const result = this.parseOptionalInteger();
  3702. if (result === null) {
  3703. throw new mlir.Error(`Expected integer value ${this.location()}`);
  3704. }
  3705. return result;
  3706. }
  3707. parseString() {
  3708. const value = this.getToken().getSpelling().str();
  3709. this.consumeToken(_.Token.string);
  3710. return value;
  3711. }
  3712. parseOptionalVerticalBar() {
  3713. return this.consumeIf(_.Token.vertical_bar);
  3714. }
  3715. parseOptionalString() {
  3716. if (!this.getToken().is(_.Token.string)) {
  3717. return null;
  3718. }
  3719. const string = this.getToken().getStringValue();
  3720. this.consumeToken();
  3721. return string;
  3722. }
  3723. getToken() {
  3724. return this.state.curToken;
  3725. }
  3726. getTokenSpelling() {
  3727. return this.state.curToken.spelling;
  3728. }
  3729. resetToken(tokPos) {
  3730. this.state.lex.resetPointer(tokPos);
  3731. this.state.curToken = this.state.lex.lexToken();
  3732. }
  3733. consumeToken(kind) {
  3734. if (kind !== undefined && this.state.curToken.kind !== kind) {
  3735. throw new mlir.Error(`consumeToken: Expected '${kind}' ${this.location()}`);
  3736. }
  3737. this.state.curToken = this.state.lex.lexToken();
  3738. }
  3739. parseToken(kind, message) {
  3740. if (this.consumeIf(kind)) {
  3741. return;
  3742. }
  3743. throw new mlir.Error(`${message || `Expected '${kind}'`} ${this.location()}`);
  3744. }
  3745. consumeIf(kind) {
  3746. if (this.state.curToken.isNot(kind)) {
  3747. return false;
  3748. }
  3749. this.consumeToken(kind);
  3750. return true;
  3751. }
  3752. location() {
  3753. return this.getToken().loc.toString();
  3754. }
  3755. static parseSymbol(inputStr, context, parserFn) {
  3756. const decoder = text.Decoder.open(inputStr);
  3757. const config = new _.ParserConfig(context);
  3758. const state = new _.ParserState(decoder, config);
  3759. const parser = new _.Parser(state, context);
  3760. const startPos = state.curToken.position || 0;
  3761. const symbol = parserFn(parser);
  3762. if (!symbol) {
  3763. return { symbol: null, numRead: 0 };
  3764. }
  3765. const endPos = parser.getToken().loc.position;
  3766. const numRead = endPos - startPos;
  3767. return { symbol, numRead };
  3768. }
  3769. static parseAttribute(attrStr, context, type = null) {
  3770. const result = _.Parser.parseSymbol(attrStr, context, (parser) => {
  3771. return parser.parseAttribute(type);
  3772. });
  3773. if (!result.symbol) {
  3774. return { attribute: null, numRead: 0 };
  3775. }
  3776. return { attribute: result.symbol, numRead: result.numRead };
  3777. }
  3778. static parseType(typeStr, context) {
  3779. const result = _.Parser.parseSymbol(typeStr, context, (parser) => {
  3780. return parser.parseType();
  3781. });
  3782. if (!result.symbol) {
  3783. return { type: null, numRead: 0 };
  3784. }
  3785. return { type: result.symbol, numRead: result.numRead };
  3786. }
  3787. };
  3788. _.TopLevelOperationParser = class extends _.Parser {
  3789. parse(block) {
  3790. const opParser = new _.OperationParser(this.state);
  3791. while (true) {
  3792. switch (this.getToken().kind) {
  3793. case _.Token.eof: {
  3794. opParser.finalize(block);
  3795. return block;
  3796. }
  3797. case _.Token.hash_identifier: {
  3798. this.parseAttributeAliasDef();
  3799. break;
  3800. }
  3801. case _.Token.exclamation_identifier: {
  3802. this.parseTypeAliasDef();
  3803. break;
  3804. }
  3805. case _.Token.file_metadata_begin: {
  3806. this.parseFileMetadataDictionary();
  3807. break;
  3808. }
  3809. default: {
  3810. const op = opParser.parseOperation();
  3811. block.operations.push(op);
  3812. }
  3813. }
  3814. }
  3815. }
  3816. parseAttributeAliasDef() {
  3817. const aliasName = this.getToken().getSpelling().str();
  3818. this.consumeToken(_.Token.hash_identifier);
  3819. this.parseToken(_.Token.equal, "Expected '=' in attribute alias definition");
  3820. let attr = null;
  3821. if (this.getToken().is(_.Token.l_paren)) {
  3822. const dims = this.skip(_.Token.l_paren);
  3823. const symbols = this.getToken().is(_.Token.l_square) ? this.skip(_.Token.l_square) : '';
  3824. this.parseToken(_.Token.arrow, "Expected '->'");
  3825. const results = this.getToken().is(_.Token.l_paren) ? this.skip(_.Token.l_paren) : '';
  3826. attr = { value: `affine_map<${dims}${symbols} -> ${results}>`, name: 'affine_map' };
  3827. } else {
  3828. attr = this.parseAttribute();
  3829. }
  3830. this.state.attributeAliasDefinitions.set(aliasName, attr);
  3831. }
  3832. parseTypeAliasDef() {
  3833. const aliasName = this.getTokenSpelling().str();
  3834. this.consumeToken(_.Token.exclamation_identifier);
  3835. this.parseToken(_.Token.equal, "Expected '=' in type alias definition");
  3836. if (this.getToken().is(_.Token.bare_identifier) && this.getTokenSpelling().str() === 'type') {
  3837. this.consumeToken(_.Token.bare_identifier);
  3838. }
  3839. const type = this.parseType();
  3840. this.state.typeAliasDefinitions.set(aliasName, type);
  3841. }
  3842. parseFileMetadataDictionary() {
  3843. this.consumeToken(_.Token.file_metadata_begin);
  3844. this.parseCommaSeparatedListUntil(_.Token.file_metadata_end, () => {
  3845. const keyLoc = this.getToken().loc;
  3846. const key = this.parseOptionalKeyword();
  3847. if (!key) {
  3848. throw new mlir.Error(`Expected identifier key in file metadata dictionary ${this.location()}`);
  3849. }
  3850. this.parseToken(_.Token.colon, "Expected ':'");
  3851. if (key === 'dialect_resources') {
  3852. this.parseDialectResourceFileMetadata();
  3853. } else if (key === 'external_resources') {
  3854. this.parseExternalResourceFileMetadata();
  3855. } else {
  3856. throw new mlir.Error(`Unknown key '${key}' in file metadata dictionary ${keyLoc.toString()}`);
  3857. }
  3858. });
  3859. }
  3860. };
  3861. // Specialized parser for affine structures (affine maps, affine expressions, integer sets)
  3862. // Following the reference implementation in AffineParser.cpp
  3863. _.AffineParser = class extends _.Parser {
  3864. constructor(state, allowParsingSSAIds = false, parseElement = null) {
  3865. super(state);
  3866. this.allowParsingSSAIds = allowParsingSSAIds;
  3867. this.parseElement = parseElement;
  3868. this.dimsAndSymbols = []; // Array of {name, expr} pairs
  3869. this.numDimOperands = 0;
  3870. this.numSymbolOperands = 0;
  3871. }
  3872. // Parse an ambiguous affine map or integer set inline
  3873. // affine-map-or-integer-set ::= dim-and-symbol-id-lists (`->` | `:`) ...
  3874. parseAffineMapOrIntegerSetInline() {
  3875. const { numDims, numSymbols } = this.parseDimAndOptionalSymbolIdList();
  3876. if (this.consumeIf(_.Token.arrow)) {
  3877. return { map: this.parseAffineMapRange(numDims, numSymbols), set: null };
  3878. }
  3879. if (!this.consumeIf(_.Token.colon)) {
  3880. throw new mlir.Error(`Expected '->' or ':' ${this.location()}`);
  3881. }
  3882. return { map: null, set: this.parseIntegerSetConstraints(numDims, numSymbols) };
  3883. }
  3884. // Parse dimension and optional symbol identifier lists: (d0, d1, ...)[s0, s1, ...]
  3885. parseDimAndOptionalSymbolIdList() {
  3886. const numDims = this.parseDimIdList();
  3887. let numSymbols = 0;
  3888. if (this.getToken().is(_.Token.l_square)) {
  3889. numSymbols = this.parseSymbolIdList();
  3890. }
  3891. return { numDims, numSymbols };
  3892. }
  3893. // Parse dimension identifier list: (d0, d1, ...)
  3894. parseDimIdList() {
  3895. let numDims = 0;
  3896. this.parseToken(_.Token.l_paren, "Expected '(' in dimensional identifier list");
  3897. if (this.getToken().isNot(_.Token.r_paren)) {
  3898. do {
  3899. const dimExpr = this.getAffineDimExpr(numDims);
  3900. this.parseIdentifierDefinition(dimExpr);
  3901. numDims++;
  3902. } while (this.consumeIf(_.Token.comma));
  3903. }
  3904. this.parseToken(_.Token.r_paren, "Expected ')' in dimensional identifier list");
  3905. return numDims;
  3906. }
  3907. // Parse symbol identifier list: [s0, s1, ...]
  3908. parseSymbolIdList() {
  3909. let numSymbols = 0;
  3910. this.parseToken(_.Token.l_square, "Expected '[' in symbol list");
  3911. if (this.getToken().isNot(_.Token.r_square)) {
  3912. do {
  3913. const symbolExpr = this.getAffineSymbolExpr(numSymbols);
  3914. this.parseIdentifierDefinition(symbolExpr);
  3915. numSymbols++;
  3916. } while (this.consumeIf(_.Token.comma));
  3917. }
  3918. this.parseToken(_.Token.r_square, "Expected ']' in symbol list");
  3919. return numSymbols;
  3920. }
  3921. parseIdentifierDefinition(idExpr) {
  3922. let name = null;
  3923. if (this.getToken().is(_.Token.bare_identifier)) {
  3924. name = this.getTokenSpelling().str();
  3925. this.consumeToken(_.Token.bare_identifier);
  3926. } else if (this.getToken().is(_.Token.inttype)) {
  3927. name = this.getTokenSpelling().str();
  3928. this.consumeToken(_.Token.inttype);
  3929. } else if (this.getToken().isKeyword()) {
  3930. name = this.getToken().getSpelling().str();
  3931. this.consumeToken();
  3932. } else {
  3933. throw new mlir.Error(`Expected bare identifier ${this.location()}`);
  3934. }
  3935. for (const entry of this.dimsAndSymbols) {
  3936. if (entry.name === name) {
  3937. throw new mlir.Error(`Redefinition of identifier '${name}' ${this.location()}`);
  3938. }
  3939. }
  3940. this.dimsAndSymbols.push({ name, expr: idExpr });
  3941. }
  3942. parseAffineMapRange(numDims, numSymbols) {
  3943. const exprs = [];
  3944. this.parseToken(_.Token.l_paren, "Expected '('");
  3945. if (this.getToken().isNot(_.Token.r_paren)) {
  3946. do {
  3947. const expr = this.parseAffineExpr();
  3948. if (!expr) {
  3949. throw new mlir.Error(`Failed to parse affine expression ${this.location()}`);
  3950. }
  3951. exprs.push(expr);
  3952. } while (this.consumeIf(_.Token.comma));
  3953. }
  3954. this.parseToken(_.Token.r_paren, "Expected ')'");
  3955. return _.AffineMap.get(numDims, numSymbols, exprs);
  3956. }
  3957. parseIntegerSetConstraints(numDims, numSymbols) {
  3958. const constraints = [];
  3959. const isEqs = [];
  3960. this.parseToken(_.Token.l_paren, "Expected '('");
  3961. if (this.getToken().isNot(_.Token.r_paren)) {
  3962. do {
  3963. const { expr, isEq } = this.parseAffineConstraint();
  3964. constraints.push(expr);
  3965. isEqs.push(isEq);
  3966. } while (this.consumeIf(_.Token.comma));
  3967. }
  3968. this.parseToken(_.Token.r_paren, "Expected ')'");
  3969. // If no constraints, return degenerate true set (0 == 0)
  3970. if (constraints.length === 0) {
  3971. const zero = this.getAffineConstantExpr(0);
  3972. return _.IntegerSet.get(numDims, numSymbols, [zero], [true]);
  3973. }
  3974. return _.IntegerSet.get(numDims, numSymbols, constraints, isEqs);
  3975. }
  3976. parseAffineConstraint() {
  3977. const lhsExpr = this.parseAffineExpr();
  3978. if (!lhsExpr) {
  3979. throw new mlir.Error(`Expected affine expression ${this.location()}`);
  3980. }
  3981. if (this.consumeIf(_.Token.greater) && this.consumeIf(_.Token.equal)) {
  3982. const rhsExpr = this.parseAffineExpr();
  3983. return { expr: this.makeSubExpr(lhsExpr, rhsExpr), isEq: false };
  3984. }
  3985. if (this.consumeIf(_.Token.less) && this.consumeIf(_.Token.equal)) {
  3986. const rhsExpr = this.parseAffineExpr();
  3987. return { expr: this.makeSubExpr(rhsExpr, lhsExpr), isEq: false };
  3988. }
  3989. if (this.consumeIf(_.Token.equal) && this.consumeIf(_.Token.equal)) {
  3990. const rhsExpr = this.parseAffineExpr();
  3991. return { expr: this.makeSubExpr(lhsExpr, rhsExpr), isEq: true };
  3992. }
  3993. throw new mlir.Error(`Expected '>=', '<=', or '==' after affine expression ${this.location()}`);
  3994. }
  3995. makeSubExpr(lhs, rhs) {
  3996. const negOne = this.getAffineConstantExpr(-1);
  3997. const negRhs = this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, rhs);
  3998. return this.getAffineBinaryOpExpr(_.AffineExprKind.Add, lhs, negRhs);
  3999. }
  4000. parseAffineExpr() {
  4001. return this.parseAffineLowPrecOpExpr(null, null);
  4002. }
  4003. parseAffineLowPrecOpExpr(llhs, llhsOp) {
  4004. const lhs = this.parseAffineOperandExpr(llhs);
  4005. if (!lhs) {
  4006. return null;
  4007. }
  4008. const lOp = this.consumeIfLowPrecOp();
  4009. if (lOp) {
  4010. if (llhs) {
  4011. const sum = this.makeAffineBinaryOp(llhsOp, llhs, lhs);
  4012. return this.parseAffineLowPrecOpExpr(sum, lOp);
  4013. }
  4014. return this.parseAffineLowPrecOpExpr(lhs, lOp);
  4015. }
  4016. const hOp = this.consumeIfHighPrecOp();
  4017. if (hOp) {
  4018. const highRes = this.parseAffineHighPrecOpExpr(lhs, hOp);
  4019. if (!highRes) {
  4020. return null;
  4021. }
  4022. const expr = llhs ? this.makeAffineBinaryOp(llhsOp, llhs, highRes) : highRes;
  4023. const nextOp = this.consumeIfLowPrecOp();
  4024. if (nextOp) {
  4025. return this.parseAffineLowPrecOpExpr(expr, nextOp);
  4026. }
  4027. return expr;
  4028. }
  4029. if (llhs) {
  4030. return this.makeAffineBinaryOp(llhsOp, llhs, lhs);
  4031. }
  4032. return lhs;
  4033. }
  4034. parseAffineHighPrecOpExpr(llhs, llhsOp) {
  4035. const lhs = this.parseAffineOperandExpr(llhs);
  4036. if (!lhs) {
  4037. return null;
  4038. }
  4039. const op = this.consumeIfHighPrecOp();
  4040. if (op) {
  4041. if (llhs) {
  4042. const expr = this.makeAffineBinaryOp(llhsOp, llhs, lhs);
  4043. return this.parseAffineHighPrecOpExpr(expr, op);
  4044. }
  4045. return this.parseAffineHighPrecOpExpr(lhs, op);
  4046. }
  4047. if (llhs) {
  4048. return this.makeAffineBinaryOp(llhsOp, llhs, lhs);
  4049. }
  4050. return lhs;
  4051. }
  4052. consumeIfLowPrecOp() {
  4053. switch (this.getToken().kind) {
  4054. case _.Token.plus:
  4055. this.consumeToken(_.Token.plus);
  4056. return _.AffineLowPrecOp.Add;
  4057. case _.Token.minus:
  4058. this.consumeToken(_.Token.minus);
  4059. return _.AffineLowPrecOp.Sub;
  4060. default:
  4061. return _.AffineLowPrecOp.LNoOp;
  4062. }
  4063. }
  4064. consumeIfHighPrecOp() {
  4065. switch (this.getToken().kind) {
  4066. case _.Token.star:
  4067. this.consumeToken(_.Token.star);
  4068. return _.AffineHighPrecOp.Mul;
  4069. case _.Token.kw_floordiv:
  4070. this.consumeToken(_.Token.kw_floordiv);
  4071. return _.AffineHighPrecOp.FloorDiv;
  4072. case _.Token.kw_ceildiv:
  4073. this.consumeToken(_.Token.kw_ceildiv);
  4074. return _.AffineHighPrecOp.CeilDiv;
  4075. case _.Token.kw_mod:
  4076. this.consumeToken(_.Token.kw_mod);
  4077. return _.AffineHighPrecOp.Mod;
  4078. default:
  4079. return _.AffineHighPrecOp.HNoOp;
  4080. }
  4081. }
  4082. // Create affine binary op expression
  4083. makeAffineBinaryOp(op, lhs, rhs) {
  4084. if (op === 'Sub') {
  4085. // Subtraction: lhs - rhs = lhs + (-1 * rhs)
  4086. const negOne = this.getAffineConstantExpr(-1);
  4087. const negRhs = this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, rhs);
  4088. return this.getAffineBinaryOpExpr(_.AffineExprKind.Add, lhs, negRhs);
  4089. }
  4090. return this.getAffineBinaryOpExpr(op, lhs, rhs);
  4091. }
  4092. parseAffineOperandExpr(lhs) {
  4093. if (this.getToken().is(_.Token.kw_symbol)) {
  4094. return this.parseSymbolSSAIdExpr();
  4095. }
  4096. if (this.getToken().is(_.Token.percent_identifier)) {
  4097. return this.parseSSAIdExpr(false);
  4098. }
  4099. if (this.getToken().is(_.Token.integer)) {
  4100. return this.parseIntegerExpr();
  4101. }
  4102. if (this.getToken().is(_.Token.l_paren)) {
  4103. return this.parseParentheticalExpr();
  4104. }
  4105. if (this.getToken().is(_.Token.minus)) {
  4106. return this.parseNegateExpression(lhs);
  4107. }
  4108. if (this.getToken().isAny(_.Token.bare_identifier, _.Token.inttype)) {
  4109. return this.parseBareIdExpr();
  4110. }
  4111. if (this.getToken().isKeyword()) {
  4112. return this.parseBareIdExpr();
  4113. }
  4114. if (this.getToken().isAny(_.Token.plus, _.Token.star)) {
  4115. if (lhs) {
  4116. throw new mlir.Error(`Missing right operand of binary operator ${this.location()}`);
  4117. }
  4118. throw new mlir.Error(`Missing left operand of binary operator ${this.location()}`);
  4119. }
  4120. if (lhs) {
  4121. throw new mlir.Error(`Missing right operand of binary operator ${this.location()}`);
  4122. }
  4123. throw new mlir.Error(`Expected affine expression ${this.location()}`);
  4124. }
  4125. parseSymbolSSAIdExpr() {
  4126. this.parseToken(_.Token.kw_symbol);
  4127. this.parseToken(_.Token.l_paren);
  4128. const symbolExpr = this.parseSSAIdExpr(true);
  4129. this.parseToken(_.Token.r_paren);
  4130. return symbolExpr;
  4131. }
  4132. parseSSAIdExpr(isSymbol) {
  4133. if (!this.allowParsingSSAIds) {
  4134. throw new mlir.Error(`Unexpected SSA identifier ${this.location()}`);
  4135. }
  4136. if (this.getToken().isNot(_.Token.percent_identifier)) {
  4137. throw new mlir.Error(`Expected SSA identifier ${this.location()}`);
  4138. }
  4139. const name = this.getTokenSpelling().str();
  4140. this.consumeToken(_.Token.percent_identifier);
  4141. for (const entry of this.dimsAndSymbols) {
  4142. if (entry.name === name) {
  4143. return entry.expr;
  4144. }
  4145. }
  4146. if (this.parseElement) {
  4147. this.parseElement(isSymbol);
  4148. }
  4149. const idExpr = isSymbol
  4150. ? this.getAffineSymbolExpr(this.numSymbolOperands++)
  4151. : this.getAffineDimExpr(this.numDimOperands++);
  4152. this.dimsAndSymbols.push({ name, expr: idExpr });
  4153. return idExpr;
  4154. }
  4155. // Parse integer literal
  4156. parseIntegerExpr() {
  4157. const val = this.getToken().getUInt64IntegerValue();
  4158. this.consumeToken(_.Token.integer);
  4159. return this.getAffineConstantExpr(Number(val));
  4160. }
  4161. // Parse parenthesized expression
  4162. parseParentheticalExpr() {
  4163. this.parseToken(_.Token.l_paren, "Expected '('");
  4164. if (this.getToken().is(_.Token.r_paren)) {
  4165. throw new mlir.Error(`No expression inside parentheses ${this.location()}`);
  4166. }
  4167. const expr = this.parseAffineExpr();
  4168. this.parseToken(_.Token.r_paren, "Expected ')'");
  4169. return expr;
  4170. }
  4171. parseNegateExpression(lhs) {
  4172. this.parseToken(_.Token.minus, "Expected '-'");
  4173. const operand = this.parseAffineOperandExpr(lhs);
  4174. if (!operand) {
  4175. throw new mlir.Error(`Missing operand of negation ${this.location()}`);
  4176. }
  4177. const negOne = this.getAffineConstantExpr(-1);
  4178. return this.getAffineBinaryOpExpr(_.AffineExprKind.Mul, negOne, operand);
  4179. }
  4180. parseBareIdExpr() {
  4181. if (!this.isCurrentTokenAKeyword()) {
  4182. throw new mlir.Error(`Expected bare identifier ${this.location()}`);
  4183. }
  4184. const name = this.getTokenSpelling().str();
  4185. this.consumeToken();
  4186. for (const entry of this.dimsAndSymbols) {
  4187. if (entry.name === name) {
  4188. return entry.expr;
  4189. }
  4190. }
  4191. throw new mlir.Error(`Use of undeclared identifier '${name}' ${this.location()}`);
  4192. }
  4193. parseAffineMapOfSSAIds(delimiter = 'Paren') {
  4194. const exprs = [];
  4195. const open = delimiter === 'Paren' ? _.Token.l_paren : _.Token.l_square;
  4196. const close = delimiter === 'Paren' ? _.Token.r_paren : _.Token.r_square;
  4197. this.parseToken(open, `Expected '${open === _.Token.l_paren ? '(' : '['}'`);
  4198. if (this.getToken().isNot(close)) {
  4199. do {
  4200. const expr = this.parseAffineExpr();
  4201. exprs.push(expr);
  4202. } while (this.consumeIf(_.Token.comma));
  4203. }
  4204. this.parseToken(close, `Expected '${close === _.Token.r_paren ? ')' : ']'}'`);
  4205. return _.AffineMap.get(this.numDimOperands, this.dimsAndSymbols.length - this.numDimOperands, exprs);
  4206. }
  4207. parseAffineExprOfSSAIds() {
  4208. return this.parseAffineExpr();
  4209. }
  4210. getAffineDimExpr(position) {
  4211. return new _.AffineDimExpr(position);
  4212. }
  4213. getAffineSymbolExpr(position) {
  4214. return new _.AffineSymbolExpr(position);
  4215. }
  4216. getAffineConstantExpr(constant) {
  4217. return new _.AffineConstantExpr(constant);
  4218. }
  4219. getAffineBinaryOpExpr(kind, lhs, rhs) {
  4220. return new _.AffineBinaryOpExpr(kind, lhs, rhs);
  4221. }
  4222. };
  4223. _.OperationParser = class extends _.Parser {
  4224. constructor(state) {
  4225. super(state);
  4226. this.isolatedNameScopes = [];
  4227. this.pushSSANameScope(/* isIsolated */ true);
  4228. this._redirect = new Map([
  4229. ['builtin.func', 'func.func'],
  4230. ['builtin.constant', 'arith.constant'],
  4231. ['builtin.return', 'func.return'],
  4232. ['builtin.select', 'arith.select'],
  4233. ['scf.select', 'arith.select'],
  4234. ['scf.call', 'func.call'],
  4235. ['builtin.view', 'memref.view'],
  4236. ['builtin.dealloc', 'memref.dealloc'], ['func.dealloc', 'memref.dealloc'],
  4237. // Arith operations (from both builtin and func default dialects)
  4238. ['builtin.addi', 'arith.addi'], ['func.addi', 'arith.addi'],
  4239. ['builtin.subi', 'arith.subi'], ['func.subi', 'arith.subi'],
  4240. ['builtin.muli', 'arith.muli'], ['func.muli', 'arith.muli'],
  4241. ['builtin.divi_signed', 'arith.divsi'], ['func.divi_signed', 'arith.divsi'],
  4242. ['builtin.divi_unsigned', 'arith.divui'], ['func.divi_unsigned', 'arith.divui'],
  4243. ['builtin.divsi', 'arith.divsi'], ['func.divsi', 'arith.divsi'],
  4244. ['builtin.divui', 'arith.divui'], ['func.divui', 'arith.divui'],
  4245. ['builtin.remi_signed', 'arith.remsi'], ['func.remi_signed', 'arith.remsi'],
  4246. ['builtin.remi_unsigned', 'arith.remui'], ['func.remi_unsigned', 'arith.remui'],
  4247. ['builtin.andi', 'arith.andi'], ['func.andi', 'arith.andi'],
  4248. ['builtin.ori', 'arith.ori'], ['func.ori', 'arith.ori'],
  4249. ['builtin.xori', 'arith.xori'], ['func.xori', 'arith.xori'],
  4250. ['builtin.shli', 'arith.shli'], ['func.shli', 'arith.shli'],
  4251. ['builtin.shrsi', 'arith.shrsi'], ['func.shrsi', 'arith.shrsi'],
  4252. ['builtin.shrui', 'arith.shrui'], ['func.shrui', 'arith.shrui'],
  4253. ['builtin.addf', 'arith.addf'], ['func.addf', 'arith.addf'],
  4254. ['builtin.subf', 'arith.subf'], ['func.subf', 'arith.subf'],
  4255. ['builtin.mulf', 'arith.mulf'], ['func.mulf', 'arith.mulf'],
  4256. ['builtin.divf', 'arith.divf'], ['func.divf', 'arith.divf'],
  4257. ['builtin.cmpi', 'arith.cmpi'], ['func.cmpi', 'arith.cmpi'],
  4258. ['builtin.cmpf', 'arith.cmpf'], ['func.cmpf', 'arith.cmpf'],
  4259. ['builtin.index_cast', 'arith.index_cast'], ['func.index_cast', 'arith.index_cast'],
  4260. ['builtin.sitofp', 'arith.sitofp'], ['func.sitofp', 'arith.sitofp'],
  4261. ['builtin.fptosi', 'arith.fptosi'], ['func.fptosi', 'arith.fptosi'],
  4262. ['builtin.truncf', 'arith.truncf'], ['func.truncf', 'arith.truncf'],
  4263. ['builtin.extf', 'arith.extf'], ['func.extf', 'arith.extf'],
  4264. ['builtin.splat', 'vector.splat'],
  4265. ['func.splat', 'vector.splat'],
  4266. ['scf.splat', 'vector.splat'],
  4267. // Memref operations
  4268. ['builtin.alloc', 'memref.alloc'], ['func.alloc', 'memref.alloc'],
  4269. ['builtin.load', 'memref.load'], ['func.load', 'memref.load'],
  4270. ['builtin.store', 'memref.store'], ['func.store', 'memref.store'],
  4271. ['builtin.subview', 'memref.subview'], ['func.subview', 'memref.subview'],
  4272. ['builtin.dim', 'memref.dim'], ['func.dim', 'memref.dim'],
  4273. ['builtin.view', 'memref.view'], ['func.view', 'memref.view'],
  4274. // Control flow operations
  4275. ['builtin.cond_br', 'cf.cond_br'], ['func.cond_br', 'cf.cond_br'],
  4276. ['builtin.br', 'cf.br'], ['func.br', 'cf.br'],
  4277. ['builtin.switch', 'cf.switch'], ['func.switch', 'cf.switch'],
  4278. ['builtin.assert', 'cf.assert'], ['func.assert', 'cf.assert'],
  4279. // Other redirects
  4280. ['flow.constant', 'flow.tensor.constant'],
  4281. ['util.initializer.return', 'util.return']
  4282. ]);
  4283. }
  4284. finalize(block) {
  4285. const attributeAliases = this.state.attributeAliasDefinitions;
  4286. const deferredRefs = this.state.deferredLocsReferences;
  4287. const resolveLocation = (opOrArgument) => {
  4288. const fwdLoc = opOrArgument.loc;
  4289. if (fwdLoc instanceof _.OpaqueLoc) {
  4290. const locInfo = deferredRefs[fwdLoc.index];
  4291. const identifier = `#${locInfo.identifier}`;
  4292. const attr = attributeAliases.get(identifier);
  4293. if (!attr) {
  4294. throw new mlir.Error(`Operation location alias '${locInfo.identifier}' was never defined.`);
  4295. }
  4296. if (attr instanceof _.LocationAttr === false) {
  4297. throw new mlir.Error(`Expected location but found '${attr}'.`);
  4298. }
  4299. opOrArgument.loc = attr;
  4300. }
  4301. };
  4302. // Walk all operations and resolve locations on ops and block arguments
  4303. const walk = (operations) => {
  4304. for (const op of operations) {
  4305. if (op.loc) {
  4306. resolveLocation(op);
  4307. }
  4308. if (op.body && op.body.blocks) {
  4309. for (const blk of op.body.blocks) {
  4310. if (blk.arguments) {
  4311. for (const arg of blk.arguments) {
  4312. if (arg.loc) {
  4313. resolveLocation(arg);
  4314. }
  4315. }
  4316. }
  4317. if (blk.operations) {
  4318. walk(blk.operations);
  4319. }
  4320. }
  4321. }
  4322. }
  4323. };
  4324. walk(block.operations);
  4325. }
  4326. parseOperation() {
  4327. const loc = this.getToken().loc.copy();
  4328. const resultIDs = [];
  4329. let numExpectedResults = 0;
  4330. if (this.getToken().is(_.Token.percent_identifier)) {
  4331. const parseNextResult = () => {
  4332. const name = this.getTokenSpelling().str();
  4333. this.consumeToken(_.Token.percent_identifier);
  4334. let expectedSubResults = 1;
  4335. if (this.consumeIf(_.Token.colon)) {
  4336. if (this.getToken().isNot(_.Token.integer)) {
  4337. throw new mlir.Error(`Expected integer number of results ${this.location()}`);
  4338. }
  4339. const val = parseInt(this.getToken().getSpelling().str(), 10);
  4340. if (!Number.isInteger(val) || val < 1) {
  4341. throw new mlir.Error(`Expected named operation to have at least 1 result ${this.location()}`);
  4342. }
  4343. this.consumeToken(_.Token.integer);
  4344. expectedSubResults *= val;
  4345. }
  4346. resultIDs.push([name, expectedSubResults, null]);
  4347. numExpectedResults += expectedSubResults;
  4348. return true;
  4349. };
  4350. this.parseCommaSeparatedList('none', parseNextResult);
  4351. this.parseToken(_.Token.equal, "Expected '=' after SSA name");
  4352. }
  4353. let op = null;
  4354. // Reference Parser.cpp:1305: nameTok.is(Token::bare_identifier) || nameTok.isKeyword()
  4355. const nameTok = this.getToken();
  4356. if (nameTok.is(_.Token.bare_identifier) || nameTok.isKeyword()) {
  4357. op = this.parseCustomOperation(resultIDs);
  4358. } else if (nameTok.is(_.Token.string)) {
  4359. op = this.parseGenericOperation();
  4360. } else {
  4361. throw new mlir.Error(`${this.getToken().is(_.Token.eof) ? 'Unexpected end of input' : `Unexpected operation name '${this.getTokenSpelling().str()}'`} ${this.location()}`);
  4362. }
  4363. if (!op) {
  4364. throw new mlir.Error(`Failed to parse operation ${this.location()}`);
  4365. }
  4366. if (resultIDs.length > 0 && op.results.length === 0) {
  4367. throw new mlir.Error(`Cannot name an operation with no results ${loc.toString()}`);
  4368. }
  4369. if (resultIDs.length > 0 && op.results.length !== numExpectedResults) {
  4370. throw new mlir.Error(`Operation '${op.name.getStringRef()}' defines '${op.results.length}' results but was provided '${numExpectedResults}' to bind ${loc.toString()}`);
  4371. }
  4372. let index = 0;
  4373. for (const resIt of resultIDs) {
  4374. for (let subRes = 0; subRes < resIt[1]; subRes++) {
  4375. const result = op.results[index++];
  4376. if (result.name) {
  4377. throw new mlir.Error(`Result '${result.name}' already has name ${this.location()}`);
  4378. }
  4379. // Workaround: Visualization-specific addition is to store name on result for display
  4380. result.name = subRes === 0 ? resIt[0] : `${resIt[0]}.${subRes}`;
  4381. this.addDefinition(new _.UnresolvedOperand(resIt[2], resIt[0], subRes), result);
  4382. }
  4383. }
  4384. return op;
  4385. }
  4386. parseCustomOperation(resultIDs) {
  4387. const opLoc = this.getToken().loc.copy();
  4388. const opNameInfo = this.parseCustomOperationName();
  4389. const opState = new _.OperationState(opLoc, opNameInfo);
  4390. delete opNameInfo.identifier; // Workaround
  4391. const defaultDialect = (opNameInfo && opNameInfo.metadata && opNameInfo.metadata.defaultDialect) || this.state.defaultDialectStack[this.state.defaultDialectStack.length - 1];
  4392. this.state.defaultDialectStack.push(defaultDialect);
  4393. const customParser = new _.CustomOpAsmParser(resultIDs, this);
  4394. if (!opNameInfo.dialect.parseOperation(customParser, opState)) {
  4395. this.state.defaultDialectStack.pop();
  4396. throw new mlir.Error(`Unsupported custom operation '${opState.identifier}' ${this.location()}`);
  4397. }
  4398. if (!opNameInfo.metadata.hasParser && !opNameInfo.metadata.hasCustomAssemblyFormat && opNameInfo.metadata.assemblyFormat && opState.compatibility !== true) {
  4399. throw new mlir.Error(`Operation '${opState.identifier}' has assembly format but was handled by custom dialect code.`);
  4400. }
  4401. opState.loc = this.parseTrailingLocationSpecifier() || {};
  4402. this.state.defaultDialectStack.pop();
  4403. return _.Operation.create(opState);
  4404. }
  4405. parseCustomOperationName() {
  4406. const nameTok = this.getToken();
  4407. if (nameTok.kind !== _.Token.bare_identifier && !nameTok.isKeyword()) {
  4408. throw new mlir.Error(`Expected bare identifier or keyword ${this.location()}`);
  4409. }
  4410. let identifier = nameTok.getSpelling().str(); // Workaround: keep the original source file identifier
  4411. this.consumeToken();
  4412. let index = identifier.indexOf('.');
  4413. if (index === -1) {
  4414. const dialect = this.state.defaultDialectStack[this.state.defaultDialectStack.length - 1];
  4415. identifier = `${dialect}.${identifier}`;
  4416. }
  4417. let opName = identifier;
  4418. if (opName === 'func.constant' && this.getToken().isNot(_.Token.at_identifier)) {
  4419. // Workaround: old std.constant should be arith.constant
  4420. opName = 'arith.constant';
  4421. } else if (opName.startsWith('check.')) {
  4422. // Workaround: Handle conflicting dialects from stablehlo and iree
  4423. const dialect = this.getToken().is(_.Token.l_paren) || this.getToken().is(_.Token.less) ? 'iree' : 'stablehlo';
  4424. opName = opName.replace('check.', `check.<${dialect}>.`);
  4425. } else if (this._redirect.has(opName)) {
  4426. opName = this._redirect.get(opName);
  4427. }
  4428. index = opName.indexOf('.');
  4429. if (index === -1) {
  4430. throw new mlir.Error(`No dialect found '${opName}' ${this.location()}`);
  4431. }
  4432. const dialectName = opName.substring(0, index);
  4433. const dialect = this.context.getOrLoadDialect(dialectName);
  4434. this.context.checkDialect(dialect, dialectName, 'operation');
  4435. // Normalize operation name to canonical dialect name for metadata lookup
  4436. // (e.g., spv.Load -> spirv.Load when dialect.name is spirv)
  4437. opName = dialectName === dialect.name ? opName : opName.replace(`${dialectName}.`, `${dialect.name}.`);
  4438. const name = _.RegisteredOperationName.lookup(opName, this.context);
  4439. if (!name) {
  4440. throw new mlir.Error(`Unsupported operation '${opName}'.`);
  4441. }
  4442. name.identifier = identifier; // Workaround
  4443. return name;
  4444. }
  4445. parseGenericOperation() {
  4446. const srcLocation = this.getToken().loc.copy();
  4447. const name = this.getToken().getStringValue();
  4448. if (name.length === 0) {
  4449. throw new mlir.Error(`Empty operation name is invalid ${this.location()}`);
  4450. }
  4451. if (name.indexOf('\0') !== -1) {
  4452. throw new mlir.Error(`Null character not allowed in operation name ${this.location()}`);
  4453. }
  4454. this.consumeToken(_.Token.string);
  4455. let opName = _.RegisteredOperationName.lookup(name, this.context);
  4456. if (!opName) {
  4457. opName = new _.OperationName(null, name);
  4458. }
  4459. opName.identifier = name; // Workaround
  4460. const state = new _.OperationState(srcLocation, opName);
  4461. this.parseGenericOperationAfterOpName(state);
  4462. return _.Operation.create(state);
  4463. }
  4464. parseGenericOperationAfterOpName(result) {
  4465. this.parseToken(_.Token.l_paren, "Expected '(' to start operand list");
  4466. const unresolvedOperands = [];
  4467. this.parseOptionalSSAUseList(unresolvedOperands);
  4468. this.parseToken(_.Token.r_paren, "Expected ')' to end operand list");
  4469. if (this.getToken().is(_.Token.l_square)) {
  4470. result.successors = [];
  4471. this.parseSuccessors(result.successors);
  4472. }
  4473. if (this.consumeIf(_.Token.less)) {
  4474. result.propertiesAttr = this.parseAttribute();
  4475. if (!result.propertiesAttr) {
  4476. throw new mlir.Error(`Expected attribute as properties ${this.location()}`);
  4477. }
  4478. this.parseToken(_.Token.greater, "Expected '>' to close properties");
  4479. }
  4480. if (this.consumeIf(_.Token.l_paren)) {
  4481. do {
  4482. const region = result.addRegion();
  4483. this.parseRegion(region, undefined, false);
  4484. } while (this.consumeIf(_.Token.comma));
  4485. this.parseToken(_.Token.r_paren, "Expected ')' to end region list");
  4486. }
  4487. if (this.getToken().is(_.Token.l_brace)) {
  4488. this.parseAttributeDict(result.attributes);
  4489. }
  4490. this.parseToken(_.Token.colon, "Expected ':' followed by operation type");
  4491. const fnType = this.parseType();
  4492. if (fnType instanceof _.FunctionType === false) {
  4493. throw new mlir.Error(`Expected function type ${this.location()}`);
  4494. }
  4495. const operandTypes = fnType.inputs;
  4496. if (operandTypes.length !== unresolvedOperands.length) {
  4497. throw new mlir.Error(`Expected ${unresolvedOperands.length} operand type${unresolvedOperands.length === 1 ? '' : 's'} but had ${operandTypes.length} ${this.location()}`);
  4498. }
  4499. for (let i = 0; i < unresolvedOperands.length; i++) {
  4500. const unresolvedOperand = unresolvedOperands[i];
  4501. const type = operandTypes[i] || null;
  4502. const value = this.resolveSSAUse(unresolvedOperand, type);
  4503. result.operands.push(value);
  4504. }
  4505. result.addTypes(fnType.results);
  4506. result.loc = this.parseTrailingLocationSpecifier();
  4507. }
  4508. pushSSANameScope(isIsolated) {
  4509. if (isIsolated) {
  4510. this.isolatedNameScopes.push(new _.IsolatedSSANameScope());
  4511. }
  4512. this.isolatedNameScopes[this.isolatedNameScopes.length - 1].pushSSANameScope();
  4513. }
  4514. popSSANameScope() {
  4515. const currentNameScope = this.isolatedNameScopes[this.isolatedNameScopes.length - 1];
  4516. if (currentNameScope.definitionsPerScope.length === 1) {
  4517. this.isolatedNameScopes.pop();
  4518. } else {
  4519. currentNameScope.popSSANameScope();
  4520. }
  4521. }
  4522. addDefinition(useInfo, value) {
  4523. const entries = this.getSSAValueEntry(useInfo.name);
  4524. if (entries.length <= useInfo.number) {
  4525. entries.length = useInfo.number + 1;
  4526. }
  4527. entries[useInfo.number] = { value, loc: useInfo.location };
  4528. this.recordDefinition(useInfo.name);
  4529. }
  4530. recordDefinition(def) {
  4531. this.isolatedNameScopes[this.isolatedNameScopes.length - 1].recordDefinition(def);
  4532. }
  4533. parseOptionalSSAUseList(results) {
  4534. if (this.getToken().isNot(_.Token.percent_identifier)) {
  4535. return;
  4536. }
  4537. this.parseCommaSeparatedList('none', () => {
  4538. const result = this.parseSSAUse();
  4539. results.push(result);
  4540. });
  4541. }
  4542. parseSSAUse(allowResultNumber = true) {
  4543. const name = this.getTokenSpelling().str();
  4544. this.parseToken(_.Token.percent_identifier, "Expected SSA operand");
  4545. let number = 0;
  4546. if (this.getToken().is(_.Token.hash_identifier)) {
  4547. if (!allowResultNumber) {
  4548. throw new mlir.Error(`Result number not allowed in argument list ${this.location()}`);
  4549. }
  4550. const value = this.getTokenSpelling().str().substring(1);
  4551. this.consumeToken(_.Token.hash_identifier);
  4552. number = parseInt(value, 10);
  4553. if (isNaN(number)) {
  4554. throw new mlir.Error(`Invalid SSA value result number '${value}' ${this.location()}`);
  4555. }
  4556. }
  4557. return new _.UnresolvedOperand(null, name, number);
  4558. }
  4559. resolveSSAUse(unresolvedOperand, type) {
  4560. if (type !== null && type instanceof _.Type === false) {
  4561. throw new mlir.Error(`Type expected instead of '${type}'.`);
  4562. }
  4563. if (unresolvedOperand instanceof _.UnresolvedOperand) {
  4564. const entries = this.getSSAValueEntry(unresolvedOperand.name);
  4565. if (unresolvedOperand.number < entries.length && entries[unresolvedOperand.number]) {
  4566. const entry = entries[unresolvedOperand.number];
  4567. if (type && entry.value) {
  4568. entry.value.type = type;
  4569. }
  4570. return entry.value;
  4571. }
  4572. const value = new _.Value(unresolvedOperand.toString(), type);
  4573. if (entries.length <= unresolvedOperand.number) {
  4574. entries.length = unresolvedOperand.number + 1;
  4575. }
  4576. entries[unresolvedOperand.number] = { value, loc: unresolvedOperand.location };
  4577. return value;
  4578. }
  4579. // Handle literal operands (e.g., integer literals for buildable types)
  4580. if (unresolvedOperand && unresolvedOperand.literal) {
  4581. return new _.Value(unresolvedOperand.name, type);
  4582. }
  4583. throw new mlir.Error(`UnresolvedOperand expected, got '${JSON.stringify(unresolvedOperand)}' ${this.location()}`);
  4584. }
  4585. getSSAValueEntry(name) {
  4586. const scope = this.isolatedNameScopes[this.isolatedNameScopes.length - 1];
  4587. if (!scope.values.has(name)) {
  4588. scope.values.set(name, []);
  4589. }
  4590. return scope.values.get(name);
  4591. }
  4592. parseBlock(block) {
  4593. block.operations = Array.isArray(block.operations) ? block.operations : [];
  4594. block.arguments = Array.isArray(block.arguments) ? block.arguments : [];
  4595. this.parseToken(_.Token.l_brace, "expected '{' to begin a region");
  4596. if (this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) {
  4597. if (this.getToken().kind === _.Token.caret_identifier) {
  4598. block.name = this.getTokenSpelling().str();
  4599. this.consumeToken(_.Token.caret_identifier);
  4600. } else {
  4601. block.name = this.getTokenSpelling().str();
  4602. this.consumeToken(_.Token.bare_identifier);
  4603. }
  4604. if (this.consumeIf(_.Token.l_paren)) {
  4605. while (!this.consumeIf(_.Token.r_paren) && this.getToken().isNot(_.Token.caret_identifier)) {
  4606. const value = this.getTokenSpelling().str();
  4607. this.consumeToken(_.Token.percent_identifier);
  4608. this.consumeToken(_.Token.colon);
  4609. const type = this.parseType();
  4610. const arg = { value, type };
  4611. const loc = this.parseTrailingLocationSpecifier();
  4612. if (loc) {
  4613. arg.loc = loc;
  4614. }
  4615. block.arguments.push(arg);
  4616. this.consumeIf(_.Token.comma);
  4617. }
  4618. }
  4619. if (block.name && block.name.endsWith(':')) {
  4620. block.name = block.name.slice(0, -1);
  4621. } else {
  4622. this.consumeToken(_.Token.colon);
  4623. }
  4624. }
  4625. while (!this.consumeIf(_.Token.r_brace)) {
  4626. if (this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) {
  4627. break;
  4628. }
  4629. const op = this.parseOperation();
  4630. block.operations.push(op);
  4631. }
  4632. block.loc = this.parseTrailingLocationSpecifier();
  4633. return block;
  4634. }
  4635. parseRegion(region, entryArguments, isIsolatedNameScope) {
  4636. // Push a new name scope for this region
  4637. this.pushSSANameScope(isIsolatedNameScope || false);
  4638. region.blocks = Array.isArray(region.blocks) ? region.blocks : [];
  4639. // Register SSA entries for entry arguments BEFORE parsing the block
  4640. // This ensures operations that reference %arg0 find the pre-registered entries
  4641. const resolvedEntryArgs = [];
  4642. if (entryArguments && entryArguments.length > 0) {
  4643. for (let i = 0; i < entryArguments.length; i++) {
  4644. const arg = entryArguments[i];
  4645. // Use explicit name if provided, otherwise generate %arg0, %arg1, etc.
  4646. const name = arg.name || `%arg${i}`;
  4647. const operand = new _.Value(name, arg.type);
  4648. // Register in SSA scope so operations can find it
  4649. this.addDefinition({ name, number: 0, location: arg.loc || null }, operand);
  4650. resolvedEntryArgs.push(operand);
  4651. }
  4652. }
  4653. const block = {};
  4654. this.parseBlock(block);
  4655. if (resolvedEntryArgs.length > 0) {
  4656. if (block.arguments.length === 0) {
  4657. block.arguments = resolvedEntryArgs;
  4658. } else if (block.arguments.length !== resolvedEntryArgs.length) {
  4659. throw new mlir.Error(`Entry block has ${block.arguments.length} arguments, but function signature has ${resolvedEntryArgs.length} ${this.location()}`);
  4660. }
  4661. }
  4662. region.blocks.push(block);
  4663. let hasMultipleBlocks = false;
  4664. while ((this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getToken().getSpelling().str() && this.getToken().getSpelling().str().startsWith('^'))) && this.getToken().isNot(_.Token.r_brace)) {
  4665. hasMultipleBlocks = true;
  4666. const nextBlock = {};
  4667. nextBlock.operations = [];
  4668. nextBlock.arguments = [];
  4669. if (this.getToken().kind === _.Token.caret_identifier) {
  4670. nextBlock.name = this.getTokenSpelling().str();
  4671. this.consumeToken(_.Token.caret_identifier);
  4672. } else {
  4673. nextBlock.name = this.getTokenSpelling().str();
  4674. this.consumeToken(_.Token.bare_identifier);
  4675. }
  4676. if (this.consumeIf(_.Token.l_paren)) {
  4677. while (!this.consumeIf(_.Token.r_paren)) {
  4678. const value = this.getTokenSpelling().str();
  4679. this.consumeToken(_.Token.percent_identifier);
  4680. this.consumeToken(_.Token.colon);
  4681. const type = this.parseType();
  4682. const arg = { value, type };
  4683. const loc = this.parseTrailingLocationSpecifier();
  4684. if (loc) {
  4685. arg.loc = loc;
  4686. }
  4687. nextBlock.arguments.push(arg);
  4688. this.consumeIf(_.Token.comma);
  4689. }
  4690. }
  4691. if (nextBlock.name && nextBlock.name.endsWith(':')) {
  4692. nextBlock.name = nextBlock.name.slice(0, -1);
  4693. } else {
  4694. this.consumeToken(_.Token.colon);
  4695. }
  4696. while (!(this.getToken().kind === _.Token.caret_identifier || (this.getToken().kind === _.Token.bare_identifier && this.getTokenSpelling().str() && this.getTokenSpelling().str().startsWith('^'))) && this.getToken().isNot(_.Token.r_brace)) {
  4697. const op = this.parseOperation();
  4698. nextBlock.operations.push(op);
  4699. }
  4700. region.blocks.push(nextBlock);
  4701. }
  4702. if (hasMultipleBlocks) {
  4703. this.consumeIf(_.Token.r_brace);
  4704. }
  4705. this.popSSANameScope();
  4706. return region;
  4707. }
  4708. parseTrailingLocationSpecifier() {
  4709. if (!this.consumeIf(_.Token.kw_loc)) {
  4710. return null;
  4711. }
  4712. this.parseToken(_.Token.l_paren, "expected '(' in location");
  4713. const tok = this.getToken();
  4714. let directLoc = null;
  4715. if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {
  4716. directLoc = this.parseLocationAlias();
  4717. } else {
  4718. directLoc = this.parseLocationInstance();
  4719. }
  4720. this.parseToken(_.Token.r_paren, "expected ')' in location");
  4721. return directLoc;
  4722. }
  4723. };
  4724. _.AsmParser = class extends _.Parser {
  4725. getNameLoc() {
  4726. return this.nameLoc;
  4727. }
  4728. parseKeyword(keyword) {
  4729. if (!this.parser.isCurrentTokenAKeyword()) {
  4730. throw new mlir.Error(`expected '${keyword || 'keyword'}' ${this.location()}`);
  4731. }
  4732. if (keyword && this.parser.getTokenSpelling().str() !== keyword) {
  4733. throw new mlir.Error(`expected '${keyword}' ${this.location()}`);
  4734. }
  4735. const spelling = this.parser.getTokenSpelling().str();
  4736. this.consumeToken();
  4737. return spelling;
  4738. }
  4739. parseOptionalKeyword(arg) {
  4740. if (typeof arg === 'string') {
  4741. const keyword = arg;
  4742. if (!this.parser.isCurrentTokenAKeyword() || this.parser.getTokenSpelling().str() !== keyword) {
  4743. return false;
  4744. }
  4745. this.consumeToken();
  4746. return true;
  4747. }
  4748. if (Array.isArray(arg)) {
  4749. const allowedValues = arg;
  4750. if (this.getToken().is(_.Token.bare_identifier) || this.getToken().isKeyword() || this.getToken().is(_.Token.inttype)) {
  4751. const value = this.getTokenSpelling().str();
  4752. if (allowedValues === undefined || allowedValues.some((v) => v === value)) {
  4753. this.consumeToken();
  4754. return value;
  4755. }
  4756. }
  4757. return null;
  4758. }
  4759. if (arg === undefined) {
  4760. return this.parser.parseOptionalKeyword();
  4761. }
  4762. throw new mlir.Error(`Invalid optional keyword ${this.location()}`);
  4763. }
  4764. parseKeywordType(keyword) {
  4765. this.parseKeyword(keyword);
  4766. return this.parseType();
  4767. }
  4768. parseTypeList() {
  4769. return this.parseTypeListNoParens();
  4770. }
  4771. parseColonType() {
  4772. this.parseToken(_.Token.colon, "expected ':'");
  4773. return this.parseType();
  4774. }
  4775. parseColonTypeList() {
  4776. this.parseToken(_.Token.colon, "expected ':'");
  4777. return this.parseTypeList();
  4778. }
  4779. parseOptionalColonTypeList() {
  4780. if (this.consumeIf(_.Token.colon)) {
  4781. return this.parseTypeList();
  4782. }
  4783. return [];
  4784. }
  4785. parseArrowTypeList() {
  4786. this.parseArrow();
  4787. return this.parseFunctionResultTypes();
  4788. }
  4789. parseOptionalArrowTypeList() {
  4790. if (this.consumeIf(_.Token.arrow)) {
  4791. return this.parseFunctionResultTypes();
  4792. }
  4793. return [];
  4794. }
  4795. parseArrow() {
  4796. this.parseToken(_.Token.arrow, "expected '->'");
  4797. }
  4798. parseOptionalArrow() {
  4799. return this.consumeIf(_.Token.arrow);
  4800. }
  4801. parseEqual() {
  4802. this.parseToken(_.Token.equal, "expected '='");
  4803. }
  4804. parseOptionalEqual() {
  4805. return this.consumeIf(_.Token.equal);
  4806. }
  4807. parseLBrace() {
  4808. this.parseToken(_.Token.l_brace, "expected '{'");
  4809. }
  4810. parseRBrace() {
  4811. this.parseToken(_.Token.r_brace, "expected '}'");
  4812. }
  4813. parseOptionalLBrace() {
  4814. return this.consumeIf(_.Token.l_brace);
  4815. }
  4816. parseOptionalRBrace() {
  4817. return this.consumeIf(_.Token.r_brace);
  4818. }
  4819. parseComma() {
  4820. this.parseToken(_.Token.comma, "expected ','");
  4821. }
  4822. parseOptionalComma() {
  4823. return this.consumeIf(_.Token.comma);
  4824. }
  4825. parseLParen() {
  4826. this.parseToken(_.Token.l_paren, "expected '('");
  4827. }
  4828. parseRParen() {
  4829. this.parseToken(_.Token.r_paren, "expected ')'");
  4830. }
  4831. parseOptionalLParen() {
  4832. return this.consumeIf(_.Token.l_paren);
  4833. }
  4834. parseOptionalRParen() {
  4835. return this.consumeIf(_.Token.r_paren);
  4836. }
  4837. parseLSquare() {
  4838. return this.parseToken(_.Token.l_square, "expected '['");
  4839. }
  4840. parseRSquare() {
  4841. return this.parseToken(_.Token.r_square, "expected ']'");
  4842. }
  4843. parseOptionalLSquare() {
  4844. return this.consumeIf(_.Token.l_square);
  4845. }
  4846. parseOptionalRSquare() {
  4847. return this.consumeIf(_.Token.r_square);
  4848. }
  4849. parseColon() {
  4850. this.parseToken(_.Token.colon, "expected ':'");
  4851. }
  4852. parseOptionalColon() {
  4853. return this.consumeIf(_.Token.colon);
  4854. }
  4855. parseLess() {
  4856. this.parseToken(_.Token.less, "expected '<'");
  4857. }
  4858. parseGreater() {
  4859. this.parseToken(_.Token.greater, "expected '>'");
  4860. }
  4861. parseOptionalLess() {
  4862. return this.consumeIf(_.Token.less);
  4863. }
  4864. parseOptionalGreater() {
  4865. return this.consumeIf(_.Token.greater);
  4866. }
  4867. parseOptionalAttrDict(attributes) {
  4868. if (this.parser.getToken().is(_.Token.l_brace)) {
  4869. this.parser.parseAttributeDict(attributes);
  4870. }
  4871. }
  4872. parseOptionalAttrDictWithKeyword(attributes) {
  4873. if (this.parseOptionalKeyword('attributes')) {
  4874. this.parser.parseAttributeDict(attributes);
  4875. }
  4876. }
  4877. parseSymbolName(attrName, attrs) {
  4878. const result = this.parseOptionalSymbolName();
  4879. if (result === null) {
  4880. throw new mlir.Error(`Expected valid '@'-identifier for symbol name ${this.location()}`);
  4881. }
  4882. attrs.set(attrName, result);
  4883. }
  4884. parseOptionalSymbolName() {
  4885. const atToken = this.parser.getToken();
  4886. if (atToken.isNot(_.Token.at_identifier)) {
  4887. return null;
  4888. }
  4889. const result = new _.StringAttr(atToken.getSymbolReference());
  4890. this.parser.consumeToken();
  4891. if (this.parser.state.asmState) {
  4892. // parser.state.asmState.addUses(SymbolRefAttr::get(result), atToken.getLocRange())
  4893. }
  4894. return result;
  4895. }
  4896. };
  4897. _.OpAsmParser = class extends _.AsmParser {
  4898. parseOptionalLocationSpecifier() {
  4899. if (!this.consumeIf(_.Token.kw_loc)) {
  4900. return null;
  4901. }
  4902. this.parseToken(_.Token.l_paren, "expected '(' in location");
  4903. const tok = this.getToken();
  4904. let directLoc = null;
  4905. if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {
  4906. directLoc = this.parseLocationAlias();
  4907. } else {
  4908. directLoc = this.parseLocationInstance();
  4909. }
  4910. this.parseToken(_.Token.r_paren, "expected ')' in location");
  4911. return directLoc;
  4912. }
  4913. parseFunctionOp(op, allowVariadic) {
  4914. this.parseOptionalVisibilityKeyword(op.attributes);
  4915. this.parseSymbolName('sym_name', op.attributes);
  4916. const sig = this.parseFunctionSignatureWithArguments(allowVariadic);
  4917. const argTypes = [];
  4918. for (const arg of sig.arguments) {
  4919. if (arg.name !== '...') {
  4920. argTypes.push(arg.type);
  4921. }
  4922. }
  4923. const type = new _.FunctionType(argTypes, sig.resultTypes);
  4924. op.addAttribute('function_type', new _.TypeAttrOf(type));
  4925. if (sig.resultAttrs.some((a) => a !== null)) {
  4926. op.addAttribute('res_attrs', sig.resultAttrs);
  4927. }
  4928. const argAttrs = sig.arguments.filter((a) => a.name !== '...').map((a) => a.attrs || null);
  4929. if (argAttrs.some((a) => a !== null)) {
  4930. op.addAttribute('arg_attrs', argAttrs);
  4931. }
  4932. this.parseOptionalAttrDictWithKeyword(op.attributes);
  4933. if (this.getToken().is(_.Token.l_brace)) {
  4934. const region = op.addRegion();
  4935. // Functions are IsolatedFromAbove, so pass true for isIsolatedNameScope
  4936. this.parseRegion(region, sig.arguments, /* isIsolatedNameScope */ true);
  4937. }
  4938. }
  4939. parseFunctionSignature(argOperands) {
  4940. const argTypes = [];
  4941. const argAttrs = [];
  4942. const resultTypes = [];
  4943. const resultAttrs = [];
  4944. this.parseToken(_.Token.l_paren, "expected '(' in function signature");
  4945. if (this.getToken().isNot(_.Token.r_paren)) {
  4946. this.parseTypeAndAttrList(argTypes, argAttrs, argOperands);
  4947. }
  4948. this.parseToken(_.Token.r_paren, "expected ')' in function signature");
  4949. if (this.consumeIf(_.Token.arrow)) {
  4950. this.parseFunctionResultList(resultTypes, resultAttrs);
  4951. }
  4952. return { argTypes, argAttrs, resultTypes, resultAttrs };
  4953. }
  4954. parseFunctionSignatureWithArguments(allowVariadic) {
  4955. const argResult = this.parseFunctionArgumentList(allowVariadic);
  4956. const resultTypes = [];
  4957. const resultAttrs = [];
  4958. if (this.consumeIf(_.Token.arrow)) {
  4959. this.parseFunctionResultList(resultTypes, resultAttrs);
  4960. }
  4961. return { arguments: argResult.arguments, isVariadic: argResult.isVariadic, resultTypes, resultAttrs };
  4962. }
  4963. parseFunctionResultList(types, attrs) {
  4964. if (this.consumeIf(_.Token.l_paren)) {
  4965. if (this.consumeIf(_.Token.r_paren)) {
  4966. return;
  4967. }
  4968. this.parseTypeAndAttrList(types, attrs);
  4969. this.parseToken(_.Token.r_paren, "expected ')' in function result list");
  4970. } else {
  4971. const type = this.parseType();
  4972. types.push(type);
  4973. attrs.push(null);
  4974. }
  4975. }
  4976. // Returns { arguments: Array<OpAsmParser.Argument>, isVariadic: boolean }
  4977. parseFunctionArgumentList(allowVariadic) {
  4978. const inputs = [];
  4979. let isVariadic = false;
  4980. if (this.consumeIf(_.Token.l_paren)) {
  4981. while (!this.consumeIf(_.Token.r_paren)) {
  4982. if (this.getToken().is(_.Token.r_paren)) {
  4983. break;
  4984. }
  4985. if (allowVariadic && this.consumeIf(_.Token.ellipsis)) {
  4986. isVariadic = true;
  4987. this.parseToken(_.Token.r_paren, "expected ')' after '...'");
  4988. break;
  4989. }
  4990. if (this.getToken().is(_.Token.percent_identifier)) {
  4991. const ssaName = this.parseOperand();
  4992. this.consumeToken(_.Token.colon);
  4993. const type = this.parseType();
  4994. let attrs = null;
  4995. if (this.getToken().is(_.Token.l_brace)) {
  4996. attrs = new Map();
  4997. this.parseAttributeDict(attrs);
  4998. }
  4999. const loc = this.parseOptionalLocationSpecifier();
  5000. inputs.push(new _.OpAsmParser.Argument(ssaName, type, attrs, loc));
  5001. } else {
  5002. // Type-only argument (no explicit name like %arg0)
  5003. // Don't generate a name - let the region/SSA system handle it
  5004. const type = this.parseType();
  5005. let attrs = null;
  5006. if (this.getToken().is(_.Token.l_brace)) {
  5007. attrs = new Map();
  5008. this.parseAttributeDict(attrs);
  5009. }
  5010. inputs.push(new _.OpAsmParser.Argument(null, type, attrs, null));
  5011. }
  5012. if (this.getToken().isNot(_.Token.r_paren)) {
  5013. if (!this.consumeIf(_.Token.comma)) {
  5014. break;
  5015. }
  5016. if (this.getToken().is(_.Token.r_paren)) {
  5017. break;
  5018. }
  5019. }
  5020. }
  5021. }
  5022. return { arguments: inputs, isVariadic };
  5023. }
  5024. parseTypeAndAttrList(types, attrs, operands) {
  5025. let index = 0;
  5026. this.parseCommaSeparatedList('none', () => {
  5027. const type = this.parseType();
  5028. types.push(type);
  5029. // Parse optional attribute dict after each type
  5030. if (this.getToken().is(_.Token.l_brace)) {
  5031. const attrList = new Map();
  5032. this.parseAttributeDict(attrList);
  5033. attrs.push(attrList);
  5034. // Associate attrs with operand if available
  5035. if (operands && index < operands.length) {
  5036. operands[index].attributes = attrList;
  5037. }
  5038. } else {
  5039. attrs.push(null);
  5040. }
  5041. index++;
  5042. return true;
  5043. });
  5044. }
  5045. parseDenseI64ArrayAttr(attributeName, attributes) {
  5046. this.parseKeyword(attributeName);
  5047. this.parseEqual();
  5048. const value = this.skip('[');
  5049. attributes.set(attributeName, value);
  5050. }
  5051. parseOptionalVisibilityKeyword(attributes) {
  5052. const visibility = this.parseOptionalKeyword(['public', 'private', 'nested']);
  5053. if (visibility) {
  5054. attributes.set('sym_visibility', visibility);
  5055. }
  5056. }
  5057. parseOperands(operands) {
  5058. this.parseCommaSeparatedList('none', () => {
  5059. operands.push(this.parseOperand());
  5060. });
  5061. }
  5062. parseShapedResultList(operands, operandTypes, resultTypes, tiedOperands) {
  5063. const tiedOperandIndices = [];
  5064. do {
  5065. let type = null;
  5066. let tiedOperandIndex = -1;
  5067. const tiedResult = this.parseOptionalOperand();
  5068. if (tiedResult) {
  5069. tiedOperandIndex = this.findTiedOperand(tiedResult, operands);
  5070. if (this.parseOptionalKeyword('as')) {
  5071. type = this.parseType();
  5072. } else if (tiedOperandIndex >= 0 && tiedOperandIndex < operandTypes.length) {
  5073. type = operandTypes[tiedOperandIndex];
  5074. }
  5075. } else {
  5076. type = this.parseType();
  5077. }
  5078. if (this.getToken().is(_.Token.l_brace)) {
  5079. this.skip(_.Token.l_brace);
  5080. }
  5081. if (type) {
  5082. resultTypes.push(type);
  5083. }
  5084. tiedOperandIndices.push(tiedOperandIndex);
  5085. } while (this.parseOptionalComma());
  5086. if (tiedOperands && tiedOperandIndices.length > 0) {
  5087. tiedOperands.push(...tiedOperandIndices);
  5088. }
  5089. }
  5090. findTiedOperand(tiedResult, operands) {
  5091. for (let i = 0; i < operands.length; i++) {
  5092. if (operands[i].name === tiedResult.name && operands[i].number === tiedResult.number) {
  5093. return i;
  5094. }
  5095. }
  5096. return -1;
  5097. }
  5098. };
  5099. _.OpAsmParser.Argument = class {
  5100. constructor(ssaName, type, attrs, loc) {
  5101. this.ssaName = ssaName;
  5102. this.type = type;
  5103. this.attrs = attrs;
  5104. this.loc = loc;
  5105. }
  5106. get name() {
  5107. return this.ssaName ? this.ssaName.name : null;
  5108. }
  5109. get value() {
  5110. return this.ssaName ? this.ssaName.toString() : null;
  5111. }
  5112. };
  5113. _.CustomOpAsmParser = class extends _.OpAsmParser {
  5114. constructor(resultIDs, parser) {
  5115. super(parser.state);
  5116. this.resultIDs = resultIDs || [];
  5117. this.parser = parser;
  5118. this.nameLoc = parser.getToken().loc.copy();
  5119. }
  5120. parseOperation() {
  5121. return this.parser.parseOperation();
  5122. }
  5123. getNumResults() {
  5124. let count = 0;
  5125. for (const entry of this.resultIDs) {
  5126. count += entry[1];
  5127. }
  5128. return count;
  5129. }
  5130. getResultName(index) {
  5131. if (index < this.resultIDs.length) {
  5132. return this.resultIDs[index][0];
  5133. }
  5134. return null;
  5135. }
  5136. parseArgument(allowType, allowAttrs) {
  5137. const ssaName = this.parseOperand();
  5138. let type = null;
  5139. let attrs = null;
  5140. let loc = null;
  5141. if (allowType) {
  5142. type = this.parseColonType();
  5143. }
  5144. if (allowAttrs) {
  5145. attrs = {};
  5146. this.parseOptionalAttrDict(attrs);
  5147. if (Object.keys(attrs).length === 0) {
  5148. attrs = null;
  5149. }
  5150. }
  5151. loc = this.parseOptionalLocationSpecifier();
  5152. return new _.OpAsmParser.Argument(ssaName, type, attrs, loc);
  5153. }
  5154. parseArgumentList(delimiter, allowType = false, allowAttrs = false) {
  5155. delimiter = delimiter || 'none';
  5156. if (delimiter === 'none') {
  5157. if (this.getToken().isNot(_.Token.percent_identifier)) {
  5158. return [];
  5159. }
  5160. }
  5161. const parseOneArgument = () => {
  5162. if (this.getToken().is(_.Token.percent_identifier)) {
  5163. return this.parseArgument(allowType, allowAttrs);
  5164. }
  5165. return null;
  5166. };
  5167. return this.parseCommaSeparatedList(delimiter, parseOneArgument);
  5168. }
  5169. parseRegion(region, entryArguments, enableNameShadowing) {
  5170. return this.parser.parseRegion(region, entryArguments, enableNameShadowing);
  5171. }
  5172. parseOperand(allowResultNumber = true) {
  5173. return this.parser.parseSSAUse(allowResultNumber);
  5174. }
  5175. parseOptionalOperand(allowResultNumber = true) {
  5176. if (this.getToken().is(_.Token.percent_identifier)) {
  5177. return this.parseOperand(allowResultNumber);
  5178. }
  5179. return null;
  5180. }
  5181. parseOperandList(delimiter) {
  5182. delimiter = delimiter || 'none';
  5183. if (delimiter === 'none') {
  5184. if (this.getToken().isNot(_.Token.percent_identifier)) {
  5185. return [];
  5186. }
  5187. }
  5188. const parseOneOperand = () => {
  5189. if (this.getToken().is(_.Token.percent_identifier)) {
  5190. return this.parseOperand();
  5191. }
  5192. return null;
  5193. };
  5194. return this.parseCommaSeparatedList(delimiter, parseOneOperand);
  5195. }
  5196. resolveOperand(operand, type, result) {
  5197. const resolved = this.parser.resolveSSAUse(operand, type);
  5198. if (result) {
  5199. result.push(resolved);
  5200. }
  5201. return resolved;
  5202. }
  5203. resolveOperands(operands, types, result) {
  5204. if (!Array.isArray(operands)) {
  5205. throw new mlir.Error(`Unexpected operands type '${typeof operands}'.`);
  5206. }
  5207. if (!Array.isArray(types)) {
  5208. return;
  5209. }
  5210. const count = Math.min(operands.length, types.length);
  5211. if (result) {
  5212. for (let i = 0; i < count; i++) {
  5213. const operand = operands[i];
  5214. const type = types[i];
  5215. const resolved = this.parser.resolveSSAUse(operand, type);
  5216. result.push(resolved);
  5217. }
  5218. } else {
  5219. for (let i = 0; i < count; i++) {
  5220. const operand = operands[i];
  5221. const type = types[i];
  5222. if (operand && type) {
  5223. if (operand instanceof _.Value) {
  5224. operand.type = type;
  5225. } else if (typeof operand === 'object') {
  5226. operand.type = type;
  5227. }
  5228. }
  5229. }
  5230. }
  5231. }
  5232. parseGenericOperation() {
  5233. return this.parser.parseGenericOperation();
  5234. }
  5235. parseCustomOperationName() {
  5236. return this.parser.parseCustomOperationName();
  5237. }
  5238. parseOptionalLocationSpecifier() {
  5239. // Ref impl: CustomOpAsmParser::parseOptionalLocationSpecifier (Parser.cpp:2002)
  5240. // Separate implementation from parseTrailingLocationSpecifier
  5241. // If there is a 'loc' we parse a trailing location.
  5242. if (!this.parser.consumeIf(_.Token.kw_loc)) {
  5243. return null;
  5244. }
  5245. this.parser.parseToken(_.Token.l_paren, "expected '(' in location");
  5246. const tok = this.parser.getToken();
  5247. let directLoc = null;
  5248. // Check to see if we are parsing a location alias. We are parsing a
  5249. // location alias if the token is a hash identifier *without* a dot in it -
  5250. // the dot signifies a dialect attribute. Otherwise, we parse the location
  5251. // directly.
  5252. if (tok.is(_.Token.hash_identifier) && !tok.getSpelling().str().includes('.')) {
  5253. directLoc = this.parser.parseLocationAlias();
  5254. } else {
  5255. directLoc = this.parser.parseLocationInstance();
  5256. }
  5257. this.parser.parseToken(_.Token.r_paren, "expected ')' in location");
  5258. return directLoc;
  5259. }
  5260. };
  5261. _.DialectAsmParser = class extends _.AsmParser {
  5262. };
  5263. _.CustomDialectAsmParser = class extends _.DialectAsmParser {
  5264. constructor(fullSpec, parser) {
  5265. super(parser.state);
  5266. this.fullSpec = fullSpec;
  5267. this.parser = parser;
  5268. this.nameLoc = parser.getToken().loc.copy();
  5269. }
  5270. };
  5271. _.TensorLiteralParser = class {
  5272. constructor(parser) {
  5273. this._parser = parser;
  5274. // Reference stores pairs of (isNegative, token) for proper type validation
  5275. // We store {isNegative, value, kind} objects
  5276. this._storage = [];
  5277. this._shape = [];
  5278. this._hexStorage = null;
  5279. }
  5280. parse(allowHex) {
  5281. if (allowHex && this._parser.getToken().is(_.Token.string)) {
  5282. const hexStr = this._parser.getToken().getStringValue();
  5283. this._parser.consumeToken(_.Token.string);
  5284. if (hexStr.startsWith('0x')) {
  5285. const cleanHex = hexStr.substring(2);
  5286. const data = new Uint8Array(cleanHex.length >> 1);
  5287. for (let i = 0; i < data.length; i++) {
  5288. const index = i << 1;
  5289. data[i] = parseInt(cleanHex.substring(index, index + 2), 16);
  5290. }
  5291. this._hexStorage = data;
  5292. return { storage: data, shape: null };
  5293. }
  5294. // Non-hex string element
  5295. this._storage.push({ isNegative: false, value: hexStr, kind: 'string' });
  5296. return { storage: this._storage, shape: this._shape };
  5297. }
  5298. if (this._parser.getToken().is(_.Token.l_square)) {
  5299. this.parseList(this._shape);
  5300. } else {
  5301. this.parseElement();
  5302. // Single element parsed without list - shape stays empty (splat)
  5303. }
  5304. return { storage: this._storage, shape: this._shape };
  5305. }
  5306. parseList(dims) {
  5307. this._parser.consumeToken(_.Token.l_square);
  5308. let first = true;
  5309. let newDims = [];
  5310. let size = 0;
  5311. while (!this._parser.consumeIf(_.Token.r_square)) {
  5312. const thisDims = [];
  5313. if (this._parser.getToken().is(_.Token.l_square)) {
  5314. this.parseList(thisDims);
  5315. } else {
  5316. this.parseElement();
  5317. }
  5318. size++;
  5319. if (!first) {
  5320. const compareDims = (a, b) =>{
  5321. if (a.length !== b.length) {
  5322. return false;
  5323. }
  5324. for (let i = 0; i < a.length; i++) {
  5325. if (a[i] !== b[i]) {
  5326. return false;
  5327. }
  5328. }
  5329. return true;
  5330. };
  5331. // Verify consistent dimensions (reference checks prevDims == newDims)
  5332. const dimsMatch = compareDims(thisDims, newDims);
  5333. if (!dimsMatch) {
  5334. throw new mlir.Error(`Tensor literal is invalid; ranks are not consistent between elements ${this._parser.location()}`);
  5335. }
  5336. }
  5337. newDims = thisDims;
  5338. first = false;
  5339. this._parser.consumeIf(_.Token.comma);
  5340. }
  5341. dims.length = 0;
  5342. dims.push(size);
  5343. dims.push(...newDims);
  5344. }
  5345. parseElement() {
  5346. switch (this._parser.getToken().kind) {
  5347. // Parse a boolean element.
  5348. case _.Token.kw_true:
  5349. case _.Token.kw_false: {
  5350. const value = this._parser.getTokenSpelling().str();
  5351. this._parser.consumeToken(this._parser.getToken().kind);
  5352. this._storage.push({ isNegative: false, value, kind: 'boolean' });
  5353. break;
  5354. }
  5355. case _.Token.floatliteral:
  5356. case _.Token.integer: {
  5357. const value = this._parser.getTokenSpelling().str();
  5358. const kind = this._parser.getToken().kind === _.Token.floatliteral ? 'float' : 'int';
  5359. this._parser.consumeToken(this._parser.getToken().kind);
  5360. this._storage.push({ isNegative: false, value, kind });
  5361. break;
  5362. }
  5363. case _.Token.minus: {
  5364. this._parser.consumeToken(_.Token.minus);
  5365. if (!this._parser.getToken().isAny(_.Token.floatliteral, _.Token.integer)) {
  5366. throw new mlir.Error(`Expected integer or floating point literal ${this._parser.location()}`);
  5367. }
  5368. const value = this._parser.getTokenSpelling().str();
  5369. const kind = this._parser.getToken().kind === _.Token.floatliteral ? 'float' : 'int';
  5370. this._parser.consumeToken(this._parser.getToken().kind);
  5371. this._storage.push({ isNegative: true, value, kind });
  5372. break;
  5373. }
  5374. case _.Token.string: {
  5375. const value = this._parser.getToken().getStringValue();
  5376. this._parser.consumeToken(_.Token.string);
  5377. this._storage.push({ isNegative: false, value, kind: 'string' });
  5378. break;
  5379. }
  5380. case _.Token.l_paren:
  5381. this._parser.consumeToken(_.Token.l_paren);
  5382. this.parseElement();
  5383. this._parser.parseToken(_.Token.comma, "expected ',' between complex elements");
  5384. this.parseElement();
  5385. this._parser.parseToken(_.Token.r_paren, "expected ')' after complex elements");
  5386. break;
  5387. default:
  5388. throw new mlir.Error(`Expected element literal of primitive type ${this._parser.location()}`);
  5389. }
  5390. }
  5391. getShape() {
  5392. return this._shape;
  5393. }
  5394. getAttr(type) {
  5395. // Handle hex storage directly
  5396. if (this._hexStorage instanceof Uint8Array) {
  5397. return this._hexStorage;
  5398. }
  5399. const elementType = type && type.elementType ? type.elementType : null;
  5400. const numElements = type && type.getNumElements ? type.getNumElements() : 0;
  5401. const isComplex = elementType instanceof _.ComplexType;
  5402. const baseElemType = isComplex && elementType.elementType ? elementType.elementType : elementType;
  5403. // Determine element type properties for validation
  5404. let isUnsigned = false;
  5405. let isInteger = false;
  5406. let isI1 = false;
  5407. let bitWidth = 0;
  5408. if (baseElemType) {
  5409. const typeStr = baseElemType.toString();
  5410. isUnsigned = typeStr.startsWith('ui');
  5411. isI1 = typeStr === 'i1';
  5412. const intMatch = typeStr.match(/^[su]?i(\d+)$/);
  5413. if (intMatch) {
  5414. isInteger = true;
  5415. bitWidth = parseInt(intMatch[1], 10);
  5416. } else if (typeStr === 'index') {
  5417. isInteger = true;
  5418. bitWidth = 64;
  5419. }
  5420. }
  5421. // Validate and convert storage elements
  5422. const convertElement = (elem) => {
  5423. const { isNegative, value, kind } = elem;
  5424. if (isNegative && isUnsigned) {
  5425. throw new mlir.Error(`Expected unsigned integer elements, but parsed negative value`);
  5426. }
  5427. if (kind === 'boolean') {
  5428. if (isInteger && !isI1) {
  5429. throw new mlir.Error(`Expected i1 type for 'true' or 'false' values`);
  5430. }
  5431. return value === true || value === 'true' ? 1 : 0;
  5432. }
  5433. if (kind === 'float' && isInteger) {
  5434. throw new mlir.Error(`Expected integer elements, but parsed floating-point`);
  5435. }
  5436. let result = null;
  5437. if (kind === 'int') {
  5438. if (bitWidth >= 64) {
  5439. result = BigInt(value);
  5440. if (isNegative) {
  5441. result = -result;
  5442. }
  5443. } else {
  5444. result = parseInt(value, 10);
  5445. if (isNegative) {
  5446. result = -result;
  5447. }
  5448. }
  5449. } else if (kind === 'float') {
  5450. result = parseFloat(value);
  5451. if (isNegative) {
  5452. result = -result;
  5453. }
  5454. } else {
  5455. result = value;
  5456. }
  5457. return result;
  5458. };
  5459. // Handle zero-element tensors (e.g., tensor<2x0x3xi4>)
  5460. if (numElements === 0) {
  5461. return [];
  5462. }
  5463. // Limit splat expansion to avoid memory issues with huge tensors
  5464. const maxSplatExpansion = 10000000;
  5465. // Handle splats - Reference: if shape.empty() and storage has elements, it's a splat
  5466. const isSplat = this._shape.length === 0 && this._storage.length > 0;
  5467. if (isSplat && numElements > 1) {
  5468. if (numElements > maxSplatExpansion) {
  5469. // Too large to expand - return null to indicate we can't provide the data
  5470. return null;
  5471. }
  5472. if (isComplex && this._storage.length === 2) {
  5473. // Complex splat: storage has 2 elements (real, imag)
  5474. const result = [];
  5475. const real = convertElement(this._storage[0]);
  5476. const imag = convertElement(this._storage[1]);
  5477. for (let i = 0; i < numElements; i++) {
  5478. result.push(new base.Complex(real, imag));
  5479. }
  5480. return result;
  5481. }
  5482. // Regular splat: replicate single value
  5483. const converted = convertElement(this._storage[0]);
  5484. return new Array(numElements).fill(converted);
  5485. }
  5486. // Non-splat complex: convert pairs to base.Complex objects
  5487. if (isComplex && Array.isArray(this._storage)) {
  5488. const result = [];
  5489. for (let i = 0; i < this._storage.length; i += 2) {
  5490. result.push(new base.Complex(convertElement(this._storage[i]), convertElement(this._storage[i + 1])));
  5491. }
  5492. return result;
  5493. }
  5494. return this._storage.map(convertElement);
  5495. }
  5496. };
  5497. _.EncodingReader = class {
  5498. constructor(data) {
  5499. if (data instanceof Uint8Array) {
  5500. this._data = data;
  5501. this._reader = base.BinaryReader.open(data);
  5502. } else {
  5503. this._data = null;
  5504. this._reader = data;
  5505. }
  5506. }
  5507. get length() {
  5508. return this._reader.length;
  5509. }
  5510. get position() {
  5511. return this._reader.position;
  5512. }
  5513. empty() {
  5514. return this.position >= this.length;
  5515. }
  5516. size() {
  5517. return this._reader.length - this._reader.position;
  5518. }
  5519. seek(offset) {
  5520. this._reader.seek(offset);
  5521. }
  5522. skipBytes(length) {
  5523. this._reader.skip(length);
  5524. }
  5525. parseBytes(length) {
  5526. return this._reader.read(length);
  5527. }
  5528. parseByte() {
  5529. return this._reader.byte();
  5530. }
  5531. peek() {
  5532. const position = this._reader.position;
  5533. const value = this._reader.byte();
  5534. this._reader.seek(position);
  5535. return value;
  5536. }
  5537. parseVarInt() {
  5538. let result = this._reader.byte();
  5539. if (result & 1) {
  5540. return BigInt(result >> 1);
  5541. }
  5542. if (result === 0) {
  5543. return this._reader.uint64();
  5544. }
  5545. result = BigInt(result);
  5546. let mask = 1n;
  5547. let numBytes = 0n;
  5548. let shift = 8n;
  5549. while (result > 0n && (result & mask) === 0n) {
  5550. if (numBytes >= 7n) {
  5551. throw new mlir.Error('Invalid varint.');
  5552. }
  5553. result |= (BigInt(this._reader.byte()) << shift);
  5554. mask <<= 1n;
  5555. shift += 8n;
  5556. numBytes++;
  5557. }
  5558. if (numBytes === 0n || numBytes > 7n) {
  5559. throw new mlir.Error(`Invalid varint.`);
  5560. }
  5561. result >>= numBytes + 1n;
  5562. return result;
  5563. }
  5564. parseSignedVarInt() {
  5565. const n = this.parseVarInt();
  5566. return (n >> 1n) ^ -(n & 1n);
  5567. }
  5568. parseVarIntWithFlag() {
  5569. const result = this.parseVarInt();
  5570. return [result >> 1n, (result & 1n) === 1n];
  5571. }
  5572. parseNullTerminatedString() {
  5573. const reader = this._reader;
  5574. let result = '';
  5575. let value = -1;
  5576. const maxLength = reader.length - reader.position;
  5577. let bytesRead = 0;
  5578. for (; ;) {
  5579. if (bytesRead >= maxLength) {
  5580. throw new mlir.Error('Malformed null-terminated string, no null character found.');
  5581. }
  5582. value = reader.byte();
  5583. bytesRead++;
  5584. if (value === 0x00) {
  5585. break;
  5586. }
  5587. result += String.fromCharCode(value);
  5588. }
  5589. return result;
  5590. }
  5591. parseEntry(entries, entryStr) {
  5592. const entryIdx = this.parseVarInt().toNumber();
  5593. return this.resolveEntry(entries, entryIdx, entryStr);
  5594. }
  5595. resolveEntry(entries, entryIdx, entryStr) {
  5596. if (entryIdx >= entries.length) {
  5597. throw new mlir.Error(`Invalid '${entryStr}' index.`);
  5598. }
  5599. return entries[entryIdx];
  5600. }
  5601. parseSection(alignmentValidator) {
  5602. const sectionIDAndHasAlignment = this.parseByte();
  5603. const length = this.parseVarInt().toNumber();
  5604. const sectionID = sectionIDAndHasAlignment & 0x7F;
  5605. const hasAlignment = sectionIDAndHasAlignment & 0x80;
  5606. if (sectionID >= 9) { // kNumSections
  5607. throw new mlir.Error(`Invalid section ID: ${sectionID}.`);
  5608. }
  5609. if (hasAlignment) {
  5610. const alignment = this.parseVarInt().toNumber();
  5611. alignmentValidator(alignment);
  5612. this.alignTo(alignment);
  5613. }
  5614. const sectionData = this.parseBytes(length);
  5615. return [sectionID, sectionData];
  5616. }
  5617. parseBlobAndAlignment() {
  5618. const alignment = this.parseVarInt().toNumber();
  5619. const dataSize = this.parseVarInt().toNumber();
  5620. this.alignTo(alignment);
  5621. const data = this.parseBytes(dataSize);
  5622. return [data, alignment];
  5623. }
  5624. alignTo(alignment) {
  5625. if ((alignment & (alignment - 1)) !== 0) {
  5626. throw new mlir.Error('Expected alignment to be a power-of-two.');
  5627. }
  5628. while ((this.position & (alignment - 1)) !== 0) {
  5629. const padding = this.parseByte();
  5630. if (padding !== 0xCB) {
  5631. throw new mlir.Error(`Expected alignment byte (0xCB), but got: 0x${padding.toString(16)}.`);
  5632. }
  5633. }
  5634. }
  5635. };
  5636. _.BytecodeDialect = class {
  5637. load(reader, ctx) {
  5638. this.dialect = ctx.getOrLoadDialect(this.name);
  5639. if (!this.dialect) {
  5640. throw new mlir.Error(`Dialect '${this.name}' is unknown.`);
  5641. }
  5642. this.interface = this.dialect;
  5643. if (this.versionBuffer) {
  5644. const encReader = new _.EncodingReader(this.versionBuffer, reader.loc);
  5645. const versionReader = reader.withEncodingReader(encReader);
  5646. const loadedVersion = this.interface.readVersion(versionReader);
  5647. if (!loadedVersion) {
  5648. return false;
  5649. }
  5650. }
  5651. return true;
  5652. }
  5653. getLoadedDialect() {
  5654. return this.dialect;
  5655. }
  5656. };
  5657. _.DialectBytecodeReader = class {
  5658. };
  5659. _.DialectReader = class extends _.DialectBytecodeReader {
  5660. constructor(attrTypeReader, stringReader, resourceReader, dialectsMap, reader, bytecodeVersion, depth = 0) {
  5661. super();
  5662. this.attrTypeReader = attrTypeReader;
  5663. this.stringReader = stringReader;
  5664. this.resourceReader = resourceReader;
  5665. this.dialectsMap = dialectsMap;
  5666. this.reader = reader;
  5667. this.bytecodeVersion = bytecodeVersion;
  5668. this.depth = depth;
  5669. this._floatBuffer = new ArrayBuffer(8);
  5670. this._floatView = new DataView(this._floatBuffer);
  5671. this._floatBitWidths = { f16: 16, bf16: 16, f32: 32, f64: 64, f80: 80, f128: 128, tf32: 19, f4E2M1FN: 4, f6E2M3FN: 6, f6E3M2FN: 6, f8E5M2: 8, f8E4M3: 8, f8E4M3FN: 8, f8E5M2FNUZ: 8, f8E4M3FNUZ: 8, f8E4M3B11FNUZ: 8, f8E3M4: 8, f8E8M0FNU: 8 };
  5672. }
  5673. readType() {
  5674. const index = this.reader.parseVarInt().toNumber();
  5675. if (this.attrTypeReader.isResolving() && this.depth > this.maxAttrTypeDepth) {
  5676. const existing = this.attrTypeReader.getTypeOrSentinel(index);
  5677. if (!existing) {
  5678. throw new mlir.Error(`Exceeded maximum type depth at '${index}'.`);
  5679. }
  5680. return existing;
  5681. }
  5682. return this.attrTypeReader.readType(index, this.depth + 1);
  5683. }
  5684. readAttribute() {
  5685. const index = this.reader.parseVarInt().toNumber();
  5686. if (this.attrTypeReader.isResolving() && this.depth > this.maxAttrTypeDepth) {
  5687. const existing = this.attrTypeReader.getAttributeOrSentinel(index);
  5688. if (!existing) {
  5689. throw new mlir.Error(`Exceeded maximum attribute depth at '${index}'.`);
  5690. }
  5691. return existing;
  5692. }
  5693. return this.attrTypeReader.readAttribute(index, this.depth + 1);
  5694. }
  5695. readString() {
  5696. return this.stringReader.parseString(this.reader);
  5697. }
  5698. readVarInt() {
  5699. return this.reader.parseVarInt().toNumber();
  5700. }
  5701. readSignedVarInt() {
  5702. return this.reader.parseSignedVarInt();
  5703. }
  5704. readByte() {
  5705. return this.reader.parseByte();
  5706. }
  5707. readBlob() {
  5708. const size = this.reader.parseVarInt().toNumber();
  5709. return this.reader.parseBytes(size);
  5710. }
  5711. readResourceHandle() {
  5712. return this.resourceReader.parseResourceHandle(this.reader);
  5713. }
  5714. readSignedVarInts() {
  5715. const count = this.reader.parseVarInt().toNumber();
  5716. const result = new Array(count);
  5717. for (let i = 0; i < count; i++) {
  5718. result[i] = this.reader.parseSignedVarInt().toNumber();
  5719. }
  5720. return result;
  5721. }
  5722. readAPIntWithKnownWidth(bitWidth) {
  5723. if (bitWidth <= 8) {
  5724. return BigInt(this.reader.parseByte());
  5725. }
  5726. if (bitWidth <= 64) {
  5727. return this.reader.parseSignedVarInt();
  5728. }
  5729. const numWords = this.reader.parseVarInt().toNumber();
  5730. let value = 0n;
  5731. for (let i = 0; i < numWords; i++) {
  5732. const word = this.reader.parseSignedVarInt();
  5733. value |= (word << BigInt(i * 64));
  5734. }
  5735. return value;
  5736. }
  5737. readAPFloatWithKnownSemantics(type) {
  5738. const bitWidth = this._floatBitWidths[type.name];
  5739. if (!bitWidth) {
  5740. throw new mlir.Error(`Unsupported float type '${type.name}'.`);
  5741. }
  5742. const bits = this.readAPIntWithKnownWidth(bitWidth);
  5743. if (bitWidth <= 32) {
  5744. this._floatView.setUint32(0, Number(bits), true);
  5745. } else {
  5746. this._floatView.setBigUint64(0, bits, true);
  5747. }
  5748. switch (type.name) {
  5749. case 'f16': return this._floatView.getFloat16(0, true);
  5750. case 'f32': return this._floatView.getFloat32(0, true);
  5751. case 'f64': return this._floatView.getFloat64(0, true);
  5752. case 'bf16': return this._floatView.getBfloat16(0, true);
  5753. default: throw new mlir.Error(`Unsupported float type '${type.name}'.`);
  5754. }
  5755. }
  5756. withEncodingReader(encodingReader) {
  5757. return new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, encodingReader, this.bytecodeVersion, this.depth);
  5758. }
  5759. };
  5760. _.AttrTypeReader = class {
  5761. constructor(stringReader, resourceReader, dialectsMap, bytecodeVersion, fileLoc, config) {
  5762. this.stringReader = stringReader;
  5763. this.resourceReader = resourceReader;
  5764. this.dialectsMap = dialectsMap;
  5765. this.fileLoc = fileLoc;
  5766. this.bytecodeVersion = bytecodeVersion;
  5767. this.parserConfig = config;
  5768. this.attributes = [];
  5769. this.types = [];
  5770. this.maxAttrTypeDepth = 5;
  5771. this._resolving = false;
  5772. }
  5773. initialize(dialects, sectionData, offsetSectionData) {
  5774. this._sectionData = sectionData;
  5775. const offsetReader = new _.EncodingReader(offsetSectionData);
  5776. const numAttributes = offsetReader.parseVarInt().toNumber();
  5777. const numTypes = offsetReader.parseVarInt().toNumber();
  5778. this.attributes = new Array(numAttributes);
  5779. this.types = new Array(numTypes);
  5780. let currentOffset = 0;
  5781. const parseEntries = (entries) => {
  5782. let currentIndex = 0;
  5783. const endIndex = entries.length;
  5784. while (currentIndex < endIndex) {
  5785. const dialectIndex = offsetReader.parseVarInt().toNumber();
  5786. const dialect = dialects[dialectIndex];
  5787. const numEntries = offsetReader.parseVarInt().toNumber();
  5788. for (let i = 0; i < numEntries; i++) {
  5789. const entry = {};
  5790. const entrySizeWithFlag = offsetReader.parseVarInt();
  5791. entry.hasCustomEncoding = (entrySizeWithFlag & 1n) === 1n;
  5792. const entrySize = (entrySizeWithFlag >> 1n).toNumber();
  5793. // Store offset like old code (don't bound reading to entry size)
  5794. entry.offset = currentOffset;
  5795. entry.size = entrySize;
  5796. entry.dialect = dialect;
  5797. entry.resolved = null;
  5798. currentOffset += entrySize;
  5799. entries[currentIndex++] = entry;
  5800. }
  5801. }
  5802. };
  5803. // Process attributes, then types
  5804. parseEntries(this.attributes);
  5805. parseEntries(this.types);
  5806. }
  5807. isResolving() {
  5808. return this._resolving;
  5809. }
  5810. getAttributeOrSentinel(index) {
  5811. if (index >= this.attributes.length) {
  5812. return null;
  5813. }
  5814. return this.attributes[index].resolved;
  5815. }
  5816. getTypeOrSentinel(index) {
  5817. if (index >= this.types.length) {
  5818. return null;
  5819. }
  5820. return this.types[index].resolved;
  5821. }
  5822. readAttribute(index, depth = 0) {
  5823. return this.readEntry(this.attributes, index, 'attr', depth);
  5824. }
  5825. readType(index, depth = 0) {
  5826. return this.readEntry(this.types, index, 'type', depth);
  5827. }
  5828. resolveAttribute(index, depth = 0) {
  5829. // Resolve an attribute at the given index (equivalent to resolveEntry in C++)
  5830. return this.resolveEntry(this.attributes, index, 'attr', depth);
  5831. }
  5832. resolveType(index, depth = 0) {
  5833. // Resolve a type at the given index (equivalent to resolveEntry in C++)
  5834. return this.resolveEntry(this.types, index, 'type', depth);
  5835. }
  5836. parseAttribute(reader) {
  5837. // Parse an attribute reference from the reader (varint index)
  5838. const index = reader.parseVarInt().toNumber();
  5839. return this.resolveAttribute(index);
  5840. }
  5841. parseType(reader) {
  5842. // Parse a type reference from the reader (varint index)
  5843. const index = reader.parseVarInt().toNumber();
  5844. return this.resolveType(index);
  5845. }
  5846. resolveEntry(entries, index, entryType, depth = 0) {
  5847. // Simplified version of C++ resolveEntry - doesn't handle deferred worklists
  5848. // but does track recursion depth
  5849. const oldResolving = this._resolving;
  5850. this._resolving = true;
  5851. try {
  5852. const result = this.readEntry(entries, index, entryType, depth);
  5853. return result;
  5854. } finally {
  5855. this._resolving = oldResolving;
  5856. }
  5857. }
  5858. readEntry(entries, index, entryType, depth = 0) {
  5859. if (index >= entries.length) {
  5860. throw new mlir.Error(`Invalid '${entryType}' index '${index}'.`);
  5861. }
  5862. const entry = entries[index];
  5863. if (entry.resolved !== null) {
  5864. return entry.resolved;
  5865. }
  5866. if (depth > this.maxAttrTypeDepth) {
  5867. throw new mlir.Error(`Exceeded maximum '${entryType}' depth.`);
  5868. }
  5869. entry.resolved = { name: 'pending', value: `<${entryType} ${index}>` };
  5870. const entryData = this._sectionData.subarray(entry.offset, entry.offset + entry.size);
  5871. const reader = new _.EncodingReader(entryData);
  5872. const startPosition = reader.position;
  5873. if (entry.hasCustomEncoding) {
  5874. entry.resolved = this.parseCustomEntry(entry, reader, entryType, index, depth);
  5875. } else {
  5876. entry.resolved = this.parseAsmEntry(reader, entryType);
  5877. }
  5878. const bytesRead = reader.position - startPosition;
  5879. if (bytesRead > entry.size) {
  5880. throw new mlir.Error(`Read ${bytesRead} bytes but entry size is ${entry.size} bytes.`);
  5881. }
  5882. return entry.resolved;
  5883. }
  5884. parseCustomEntry(entry, reader, entryType, index, depth) {
  5885. // Lazy load the dialect interface (like BytecodeDialect::load)
  5886. const context = this.fileLoc.context;
  5887. if (entry.dialect.interface === undefined) {
  5888. entry.dialect.interface = context.getOrLoadDialect(entry.dialect.name);
  5889. }
  5890. context.checkDialect(entry.dialect.interface, entry.dialect.name, 'custom entry');
  5891. const dialect = entry.dialect.interface;
  5892. const dialectReader = new _.DialectReader(this, this.stringReader, this.resourceReader, this.dialectsMap, reader, this.version, depth);
  5893. switch (entryType) {
  5894. case 'type':
  5895. return dialect.readType(dialectReader);
  5896. case 'attr':
  5897. return dialect.readAttribute(dialectReader);
  5898. default:
  5899. throw new mlir.Error(`Unknown entry type '${entryType}'.`);
  5900. }
  5901. }
  5902. parseAsmEntry(reader, entryType) {
  5903. const asmStr = reader.parseNullTerminatedString();
  5904. const context = this.fileLoc.context;
  5905. if (entryType === 'type') {
  5906. const { type, numRead } = _.Parser.parseType(asmStr, context);
  5907. if (!type || numRead !== asmStr.length) {
  5908. throw new mlir.Error(`Failed to parse type '${asmStr}'.`);
  5909. }
  5910. return type;
  5911. }
  5912. const { attribute, numRead } = _.Parser.parseAttribute(asmStr, context, null);
  5913. if (!attribute || numRead !== asmStr.length) {
  5914. throw new mlir.Error(`Failed to parse attribute '${asmStr}'.`);
  5915. }
  5916. return attribute;
  5917. }
  5918. };
  5919. _.StringSectionReader = class {
  5920. initialize(sectionData) {
  5921. const decoder = new TextDecoder('utf-8');
  5922. const stringReader = new _.EncodingReader(sectionData);
  5923. const numStrings = stringReader.parseVarInt().toNumber();
  5924. this.strings = new Array(numStrings);
  5925. let stringDataEndOffset = sectionData.length;
  5926. for (let i = numStrings - 1; i >= 0; i--) {
  5927. const stringSize = stringReader.parseVarInt().toNumber();
  5928. if (stringDataEndOffset < stringSize) {
  5929. throw new mlir.Error('String size exceeds the available data size.');
  5930. }
  5931. const stringOffset = stringDataEndOffset - stringSize;
  5932. const buffer = sectionData.subarray(stringOffset, stringOffset + stringSize - 1);
  5933. this.strings[i] = decoder.decode(buffer);
  5934. stringDataEndOffset = stringOffset;
  5935. }
  5936. if ((sectionData.length - stringReader.size()) !== stringDataEndOffset) {
  5937. throw new mlir.Error('Unexpected trailing data between the offsets for strings and their data.');
  5938. }
  5939. }
  5940. parseString(reader) {
  5941. return reader.parseEntry(this.strings, 'string');
  5942. }
  5943. parseStringWithFlag(reader) {
  5944. const [entryIdx, flag] = reader.parseVarIntWithFlag();
  5945. const str = this.parseStringAtIndex(reader, entryIdx.toNumber());
  5946. return [str, flag];
  5947. }
  5948. parseStringAtIndex(reader, index) {
  5949. if (index >= this.strings.length) {
  5950. throw new mlir.Error('Invalid string index.');
  5951. }
  5952. return this.strings[index];
  5953. }
  5954. };
  5955. _.PropertiesSectionReader = class {
  5956. constructor() {
  5957. this._properties = new Map();
  5958. }
  5959. initialize(sectionData) {
  5960. const reader = new _.EncodingReader(sectionData);
  5961. const count = reader.parseVarInt().toNumber();
  5962. this._properties = new Array(count);
  5963. for (let i = 0; i < this._properties.length; i++) {
  5964. const size = reader.parseVarInt().toNumber();
  5965. const data = reader.parseBytes(size);
  5966. this._properties[i] = data;
  5967. }
  5968. }
  5969. read(fileLoc, dialectReader, opName, opState) {
  5970. const propIdx = dialectReader.readVarInt();
  5971. if (propIdx < this._properties.length) {
  5972. const propData = this._properties[propIdx];
  5973. if (propData.length > 0) {
  5974. const propReader = dialectReader.withEncodingReader(new _.EncodingReader(propData));
  5975. // Reference: https://github.com/llvm/llvm-project/blob/main/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
  5976. // Function operations: sym_name (required), function_type (required), arg_attrs (optional), res_attrs (optional)
  5977. if (opName.getStringRef().endsWith('.func') || /\.func_v\d+$/.test(opName.getStringRef())) {
  5978. if (propReader.reader.position < propData.length) {
  5979. const symNameAttr = propReader.readAttribute();
  5980. if (symNameAttr && symNameAttr.value !== undefined) {
  5981. const name = typeof symNameAttr.value === 'string' ? symNameAttr.value : String(symNameAttr.value);
  5982. opState.addAttribute('sym_name', new _.StringAttr(name));
  5983. }
  5984. }
  5985. if (propReader.reader.position < propData.length) {
  5986. const funcTypeAttr = propReader.readAttribute();
  5987. if (funcTypeAttr instanceof _.TypeAttrOf && funcTypeAttr.type instanceof _.FunctionType) {
  5988. opState.addAttribute('function_type', funcTypeAttr);
  5989. }
  5990. }
  5991. if (propReader.reader.position < propData.length) {
  5992. const argAttrs = propReader.readAttribute();
  5993. if (argAttrs) {
  5994. opState.addAttribute('arg_attrs', argAttrs);
  5995. }
  5996. }
  5997. if (propReader.reader.position < propData.length) {
  5998. const resAttrs = propReader.readAttribute();
  5999. if (resAttrs) {
  6000. opState.addAttribute('res_attrs', resAttrs);
  6001. }
  6002. }
  6003. return;
  6004. }
  6005. if (opName.getStringRef().includes('.constant') || opName.getStringRef().endsWith('.const')) {
  6006. if (propReader.reader.position < propData.length) {
  6007. const attr = propReader.readAttribute();
  6008. if (attr !== null && attr !== undefined) {
  6009. opState.addAttribute('value', attr);
  6010. }
  6011. }
  6012. }
  6013. }
  6014. }
  6015. }
  6016. };
  6017. _.AsmResourceEntryKind = {
  6018. Blob: 0,
  6019. Bool: 1,
  6020. String: 2
  6021. };
  6022. _.ParsedResourceEntry.Bytecode = class {
  6023. constructor(key, kind, reader, stringReader) {
  6024. this.key = key;
  6025. this.kind = kind;
  6026. this.reader = reader;
  6027. this.stringReader = stringReader;
  6028. }
  6029. parseAsBlob() {
  6030. if (this.kind === _.AsmResourceEntryKind.Blob) {
  6031. const [data] = this.reader.parseBlobAndAlignment();
  6032. return data;
  6033. }
  6034. return null;
  6035. }
  6036. };
  6037. _.ResourceSectionReader = class {
  6038. constructor() {
  6039. this.dialectResources = [];
  6040. this.dialectResourceHandleRenamingMap = new Map();
  6041. }
  6042. initialize(fileLoc, config, dialects, stringReader, sectionData, offsetSectionData, dialectReader) {
  6043. const resourceReader = new _.EncodingReader(sectionData);
  6044. const offsetReader = new _.EncodingReader(offsetSectionData);
  6045. const numExternalResourceGroups = offsetReader.parseVarInt().toNumber();
  6046. const parseGroup = (handler, allowEmpty = false, processKeyFn = null) => {
  6047. const resolveKey = (key) => {
  6048. const remapped = this.dialectResourceHandleRenamingMap.get(key);
  6049. return remapped === undefined ? key : remapped;
  6050. };
  6051. return this.parseResourceGroup(fileLoc, allowEmpty, offsetReader, resourceReader, stringReader, handler, resolveKey, processKeyFn);
  6052. };
  6053. for (let i = 0; i < numExternalResourceGroups; i++) {
  6054. const key = stringReader.parseString(offsetReader);
  6055. const handler = config && config.getResourceParser ? config.getResourceParser(key) : null;
  6056. if (!parseGroup(handler)) {
  6057. return false;
  6058. }
  6059. }
  6060. const ctx = fileLoc.context;
  6061. while (!offsetReader.empty()) {
  6062. const dialect = offsetReader.parseEntry(dialects, "dialect");
  6063. dialect.load(dialectReader, ctx);
  6064. const handler = dialect.getLoadedDialect();
  6065. if (!handler) {
  6066. throw new mlir.Error(`Unknown dialect '${dialect.name}'.`);
  6067. }
  6068. const processResourceKeyFn = (key) => {
  6069. const handle = handler.declareResource(key);
  6070. if (!handle) {
  6071. throw new mlir.Error(`Unknown 'resource' key '${key}' for dialect '${dialect.name}'.`);
  6072. }
  6073. this.dialectResourceHandleRenamingMap.set(key, handler.getResourceKey(handle));
  6074. this.dialectResources.push(handler);
  6075. return true;
  6076. };
  6077. if (!parseGroup(handler, true, processResourceKeyFn)) {
  6078. return false;
  6079. }
  6080. }
  6081. return true;
  6082. }
  6083. parseResourceGroup(fileLoc, allowEmpty, offsetReader, resourceReader, stringReader, handler, remapKey, processKeyFn) {
  6084. const numResources = offsetReader.parseVarInt().toNumber();
  6085. for (let i = 0; i < numResources; i++) {
  6086. const key = stringReader.parseString(offsetReader);
  6087. const resourceOffset = offsetReader.parseVarInt().toNumber();
  6088. const kind = offsetReader.parseByte();
  6089. const data = resourceReader.parseBytes(resourceOffset);
  6090. if (processKeyFn && !processKeyFn(key)) {
  6091. return false;
  6092. }
  6093. if (allowEmpty && data.length === 0) {
  6094. continue;
  6095. }
  6096. const entryReader = new _.EncodingReader(data);
  6097. const resolvedKey = remapKey ? remapKey(key) : key;
  6098. const entry = new _.ParsedResourceEntry.Bytecode(resolvedKey, kind, entryReader, stringReader);
  6099. if (!handler) {
  6100. continue;
  6101. }
  6102. handler.parseResource(entry);
  6103. if (!entryReader.empty()) {
  6104. throw new mlir.Error(`Unexpected trailing bytes in resource entry '${resolvedKey}'.`);
  6105. }
  6106. }
  6107. return true;
  6108. }
  6109. parseResourceHandle(reader) {
  6110. return reader.parseEntry(this.dialectResources, "resource handle");
  6111. }
  6112. };
  6113. _.Location = class {
  6114. constructor(context) {
  6115. this.context = context;
  6116. }
  6117. };
  6118. _.LocationAttr = class {
  6119. constructor() {
  6120. this.name = 'loc';
  6121. }
  6122. get value() {
  6123. return 'unknown';
  6124. }
  6125. };
  6126. _.UnknownLoc = class extends _.LocationAttr {
  6127. get value() {
  6128. return 'unknown';
  6129. }
  6130. };
  6131. _.FileLineColLoc = class extends _.LocationAttr {
  6132. constructor(filename, line, col) {
  6133. super();
  6134. this.filename = filename;
  6135. this.line = line;
  6136. this.col = col;
  6137. }
  6138. get value() {
  6139. return `${this.filename}:${this.line}:${this.col}`;
  6140. }
  6141. };
  6142. _.FileLineColRange = class extends _.LocationAttr {
  6143. constructor(filename, startLine, startCol, endLine, endCol) {
  6144. super();
  6145. this.filename = filename;
  6146. this.startLine = startLine;
  6147. this.startCol = startCol;
  6148. this.endLine = endLine;
  6149. this.endCol = endCol;
  6150. }
  6151. get value() {
  6152. if (this.endLine !== undefined && this.endCol !== undefined) {
  6153. return `${this.filename}:${this.startLine}:${this.startCol} to ${this.endLine}:${this.endCol}`;
  6154. }
  6155. if (this.endCol !== undefined) {
  6156. return `${this.filename}:${this.startLine}:${this.startCol} to :${this.endCol}`;
  6157. }
  6158. if (this.startCol !== undefined) {
  6159. return `${this.filename}:${this.startLine}:${this.startCol}`;
  6160. }
  6161. return `${this.filename}:${this.startLine}`;
  6162. }
  6163. };
  6164. _.NameLoc = class extends _.LocationAttr {
  6165. constructor(name, childLoc) {
  6166. super();
  6167. this._name = name;
  6168. this.childLoc = childLoc;
  6169. }
  6170. get value() {
  6171. if (this.childLoc) {
  6172. const childStr = this.childLoc.value || this.childLoc;
  6173. return `"${this._name}"(${childStr})`;
  6174. }
  6175. return `"${this._name}"`;
  6176. }
  6177. };
  6178. _.CallSiteLoc = class extends _.LocationAttr {
  6179. constructor(callee, caller) {
  6180. super();
  6181. this.callee = callee;
  6182. this.caller = caller;
  6183. }
  6184. get value() {
  6185. const calleeStr = this.callee && this.callee.value ? this.callee.value : this.callee;
  6186. const callerStr = this.caller && this.caller.value ? this.caller.value : this.caller;
  6187. return `callsite(${calleeStr} at ${callerStr})`;
  6188. }
  6189. };
  6190. _.FusedLoc = class extends _.LocationAttr {
  6191. constructor(locations, metadata) {
  6192. super();
  6193. this.locations = locations;
  6194. this.metadata = metadata;
  6195. }
  6196. get value() {
  6197. const locStrs = this.locations.map((loc) => loc && loc.value ? loc.value : loc);
  6198. if (this.metadata) {
  6199. const metaStr = this.metadata.value === undefined ? this.metadata : this.metadata.value;
  6200. return `fused<${metaStr}>[${locStrs.join(', ')}]`;
  6201. }
  6202. return `fused[${locStrs.join(', ')}]`;
  6203. }
  6204. };
  6205. _.XtenNNDictLoc = class extends _.LocationAttr {
  6206. constructor(dictContent) {
  6207. super();
  6208. this.dictContent = dictContent;
  6209. }
  6210. get value() {
  6211. return `#xten_nn<dict_loc(${this.dictContent}`;
  6212. }
  6213. };
  6214. _.OpaqueLoc = class extends _.LocationAttr {
  6215. constructor(index, identifier, fallbackLoc) {
  6216. super();
  6217. this.index = index;
  6218. this.identifier = identifier;
  6219. this.fallbackLoc = fallbackLoc || new _.UnknownLoc();
  6220. }
  6221. get value() {
  6222. return this.fallbackLoc.value;
  6223. }
  6224. };
  6225. _.BytecodeReader = class {
  6226. constructor(reader, config) {
  6227. this.reader = new _.EncodingReader(reader);
  6228. this.fileLoc = new _.Location(config.context);
  6229. this.valueScopes = [];
  6230. this.opNames = [];
  6231. this.dialects = [];
  6232. this.dialectsMap = new Map();
  6233. this.resourceReader = new _.ResourceSectionReader();
  6234. this.stringReader = new _.StringSectionReader();
  6235. this.propertiesReader = new _.PropertiesSectionReader();
  6236. this.attrTypeReader = new _.AttrTypeReader(this.stringReader, this.resourceReader, this.dialectsMap, this.version, this.fileLoc, this.config);
  6237. // Store buffer start address for alignment validation
  6238. this._bufferStart = reader instanceof Uint8Array ? reader.byteOffset : 0;
  6239. }
  6240. read() {
  6241. const reader = this.reader;
  6242. const signature = reader.parseBytes(4);
  6243. if (String.fromCharCode(...signature) !== 'ML\xEFR') {
  6244. throw new mlir.Error('Invalid MLIR bytecode signature.');
  6245. }
  6246. this.parseVersion(reader);
  6247. this.producer = reader.parseNullTerminatedString();
  6248. const sectionDatas = new Map();
  6249. while (reader.position < reader.length) {
  6250. const sectionIDAndHasAlignment = reader.parseByte();
  6251. const sectionID = sectionIDAndHasAlignment & 0x7F;
  6252. const length = reader.parseVarInt().toNumber();
  6253. const hasAlignment = sectionIDAndHasAlignment & 0x80;
  6254. if (sectionID >= 9) {
  6255. throw new mlir.Error(`Unsupported section identifier '${sectionID}'.`);
  6256. }
  6257. if (hasAlignment) {
  6258. const alignment = reader.parseVarInt().toNumber();
  6259. this.checkSectionAlignment(alignment);
  6260. reader.alignTo(alignment);
  6261. }
  6262. const sectionData = reader.parseBytes(length);
  6263. sectionDatas.set(sectionID, sectionData);
  6264. }
  6265. for (let sectionID = 0; sectionID < 9; sectionID++) {
  6266. if (sectionDatas.has(sectionID)) {
  6267. continue;
  6268. }
  6269. if (sectionID <= 4 || (sectionID === 8 && this.version >= 5)) { // kString, kDialect, kAttrType, kAttrTypeOffset, kIR, kProperties + kNativePropertiesEncoding
  6270. throw new mlir.Error(`Missing section '${sectionID}'.`);
  6271. }
  6272. }
  6273. this.stringReader.initialize(sectionDatas.get(0));
  6274. if (sectionDatas.has(8)) {
  6275. this.propertiesReader.initialize(sectionDatas.get(8));
  6276. }
  6277. this.parseDialectSection(sectionDatas.get(1));
  6278. this.parseResourceSection(sectionDatas.get(5), sectionDatas.get(6));
  6279. this.attrTypeReader.initialize(this.dialects, sectionDatas.get(2), sectionDatas.get(3));
  6280. return this.parseIRSection(sectionDatas.get(4));
  6281. }
  6282. checkSectionAlignment(alignment) {
  6283. // Check that the bytecode buffer meets the requested section alignment.
  6284. // In JavaScript, we validate the byteOffset within the ArrayBuffer.
  6285. // This ensures the buffer offset is aligned to the requested alignment.
  6286. if (!Number.isInteger(alignment) || alignment <= 0 || (alignment & (alignment - 1)) !== 0) {
  6287. throw new mlir.Error(`Invalid alignment value: ${alignment} (must be a power of 2).`);
  6288. }
  6289. const isGloballyAligned = (this._bufferStart & (alignment - 1)) === 0;
  6290. if (!isGloballyAligned) {
  6291. throw new mlir.Error(`Expected section alignment ${alignment} but bytecode buffer offset 0x${this._bufferStart.toString(16)} is not aligned.`);
  6292. }
  6293. }
  6294. parseVersion(reader) {
  6295. this.version = reader.parseVarInt().toNumber();
  6296. const kVersion = 6;
  6297. const kMinSupportedVersion = 0;
  6298. if (this.version < kMinSupportedVersion || this.version > kVersion) {
  6299. throw new mlir.Error(`Unsupported MLIR bytecode version '${this.version}'.`);
  6300. }
  6301. }
  6302. parseDialectSection(sectionData) {
  6303. const sectionReader = new _.EncodingReader(sectionData);
  6304. const numDialects = sectionReader.parseVarInt().toNumber();
  6305. const checkSectionAlignment = (alignment) => {
  6306. this.checkSectionAlignment(alignment);
  6307. };
  6308. for (let i = 0; i < numDialects; i++) {
  6309. this.dialects.push(new _.BytecodeDialect());
  6310. if (this.version < 1) { // kDialectVersioning
  6311. this.dialects[i].name = this.stringReader.parseString();
  6312. continue;
  6313. }
  6314. const [dialectNameIdx, versionAvailable] = sectionReader.parseVarIntWithFlag();
  6315. this.dialects[i].name = this.stringReader.parseStringAtIndex(sectionReader, dialectNameIdx.toNumber());
  6316. if (versionAvailable) {
  6317. const [sectionID, versionBuffer] = sectionReader.parseSection(checkSectionAlignment);
  6318. this.dialects[i].versionBuffer = versionBuffer;
  6319. if (sectionID !== 7) { // kDialectVersion
  6320. throw new mlir.Error(`Expected dialect version section.`);
  6321. }
  6322. }
  6323. }
  6324. let index = 0;
  6325. let numOps = -1;
  6326. const parseOpName = (dialect) => {
  6327. const opName = {};
  6328. opName.dialect = dialect;
  6329. if (this.version < 5) { // kNativePropertiesEncoding
  6330. opName.name = this.stringReader.parseString(sectionReader);
  6331. } else {
  6332. [opName.name, opName.wasRegistered] = this.stringReader.parseStringWithFlag(sectionReader);
  6333. }
  6334. if (numOps < 0) {
  6335. this.opNames.push(opName);
  6336. } else {
  6337. this.opNames[index++] = opName;
  6338. }
  6339. };
  6340. if (this.version >= 4) { // kElideUnknownBlockArgLocation
  6341. numOps = sectionReader.parseVarInt().toNumber();
  6342. this.opNames = new Array(numOps);
  6343. }
  6344. while (sectionReader.position < sectionData.length) {
  6345. _.BytecodeReader.parseDialectGrouping(sectionReader, this.dialects, parseOpName);
  6346. }
  6347. }
  6348. parseResourceSection(resourceData, resourceOffsetData) {
  6349. if (!resourceOffsetData) {
  6350. return true;
  6351. }
  6352. const dialectReader = new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, new _.EncodingReader(resourceData || new Uint8Array(0)), this.version);
  6353. return this.resourceReader.initialize(this.fileLoc, this.config, this.dialects, this.stringReader, resourceData, resourceOffsetData, dialectReader);
  6354. }
  6355. parseIRSection(sectionData) {
  6356. const reader = new _.EncodingReader(sectionData);
  6357. const block = { operations: [] };
  6358. this.valueScopes = [[]];
  6359. const regionStack = [{
  6360. block,
  6361. curRegion: 0,
  6362. numRegions: 1,
  6363. curBlock: 0,
  6364. numBlocks: 1,
  6365. numOpsRemaining: 0,
  6366. numValues: 0,
  6367. blocks: [block],
  6368. nextValueIdx: 0,
  6369. isTopLevel: true,
  6370. reader
  6371. }];
  6372. const firstBlockHeader = this.parseBlockHeader(reader);
  6373. regionStack[0].numOpsRemaining = firstBlockHeader.numOps;
  6374. if (firstBlockHeader.hasArgs) {
  6375. const [scope] = this.valueScopes;
  6376. this.parseBlockArguments(reader, block, scope, 0);
  6377. regionStack[0].nextValueIdx = block.arguments ? block.arguments.length : 0;
  6378. }
  6379. // Iteratively parse regions until everything has been resolved.
  6380. while (regionStack.length > 0) {
  6381. this.parseRegions(regionStack, regionStack[regionStack.length - 1]);
  6382. }
  6383. return block;
  6384. }
  6385. parseRegion(readState) {
  6386. const reader = readState.reader;
  6387. const numBlocks = reader.parseVarInt().toNumber();
  6388. if (numBlocks === 0) {
  6389. return false;
  6390. }
  6391. const numValues = reader.parseVarInt().toNumber();
  6392. readState.numValues = numValues;
  6393. readState.numBlocks = numBlocks;
  6394. // Create the blocks within this region.
  6395. const blocks = [];
  6396. for (let j = 0; j < numBlocks; j++) {
  6397. blocks.push({ operations: [], arguments: [] });
  6398. }
  6399. readState.blocks = blocks;
  6400. readState.region.blocks = blocks;
  6401. // Prepare the current value scope for this region.
  6402. const scope = this.valueScopes[this.valueScopes.length - 1];
  6403. const valueOffset = scope.length;
  6404. readState.valueOffset = valueOffset;
  6405. for (let j = 0; j < numValues; j++) {
  6406. scope.push(null);
  6407. }
  6408. // Parse the entry block of the region.
  6409. readState.curBlock = 0;
  6410. const blockHeader = this.parseBlockHeader(reader);
  6411. readState.numOpsRemaining = blockHeader.numOps;
  6412. if (blockHeader.hasArgs) {
  6413. this.parseBlockArguments(reader, blocks[0], scope, valueOffset);
  6414. }
  6415. const numBlockArgs = blocks[0].arguments ? blocks[0].arguments.length : 0;
  6416. readState.nextValueIdx = valueOffset + numBlockArgs;
  6417. return true;
  6418. }
  6419. parseRegions(regionStack, readState) {
  6420. const reader = readState.reader;
  6421. while (true) {
  6422. while (readState.numOpsRemaining > 0) {
  6423. readState.numOpsRemaining--;
  6424. // Read in the next operation. We don't read its regions directly,
  6425. // we handle those afterwards as necessary.
  6426. const { state: opState, resultNames, isIsolatedFromAbove, resultIndices } = this.parseOpWithoutRegions(reader, readState);
  6427. const op = _.Operation.create(opState);
  6428. // Assign result names for Netron display (reference: names are in parser symbol table)
  6429. // Also update the value scope to replace placeholders with actual OpResult objects
  6430. const scope = this.valueScopes[this.valueScopes.length - 1];
  6431. for (let i = 0; i < resultNames.length && i < op.results.length; i++) {
  6432. op.results[i].name = resultNames[i];
  6433. // Replace placeholder in scope with actual result
  6434. if (resultIndices && i < resultIndices.length) {
  6435. const valueIdx = resultIndices[i];
  6436. if (valueIdx < scope.length) {
  6437. scope[valueIdx] = op.results[i];
  6438. }
  6439. }
  6440. }
  6441. readState.blocks[readState.curBlock].operations.push(op);
  6442. if (op.regions && op.regions.length > 0) {
  6443. for (let i = op.regions.length - 1; i >= 0; i--) {
  6444. const region = op.regions[i];
  6445. const childState = {
  6446. region,
  6447. curRegion: 0,
  6448. numRegions: 1,
  6449. curBlock: 0,
  6450. numBlocks: 0,
  6451. numOpsRemaining: 0,
  6452. numValues: 0,
  6453. blocks: [],
  6454. valueOffset: 0,
  6455. nextValueIdx: 0,
  6456. isIsolated: isIsolatedFromAbove,
  6457. reader,
  6458. owningReader: null
  6459. };
  6460. // Isolated regions are encoded as a section in version 2 and above.
  6461. if (this.version >= 2 && isIsolatedFromAbove) { // kLazyLoading
  6462. const checkSectionAlignment = (alignment) => {
  6463. this.checkSectionAlignment(alignment);
  6464. };
  6465. const [sectionID, sectionData] = reader.parseSection(checkSectionAlignment);
  6466. if (sectionID !== 4) { // kIR
  6467. throw new mlir.Error(`Expected IR section for region.`);
  6468. }
  6469. childState.owningReader = new _.EncodingReader(sectionData);
  6470. childState.reader = childState.owningReader;
  6471. }
  6472. // If the op is isolated from above, push a new value scope.
  6473. if (isIsolatedFromAbove) {
  6474. this.valueScopes.push([]);
  6475. }
  6476. // Parse the region and push to stack if non-empty
  6477. if (this.parseRegion(childState)) {
  6478. regionStack.push(childState);
  6479. return;
  6480. }
  6481. }
  6482. }
  6483. }
  6484. // Move to the next block of the region.
  6485. readState.curBlock++;
  6486. if (readState.curBlock >= readState.numBlocks) {
  6487. break;
  6488. }
  6489. const blockHeader = this.parseBlockHeader(reader);
  6490. readState.numOpsRemaining = blockHeader.numOps;
  6491. if (blockHeader.hasArgs) {
  6492. const scope = this.valueScopes[this.valueScopes.length - 1];
  6493. const argOffset = readState.nextValueIdx === undefined ? 0 : readState.nextValueIdx;
  6494. this.parseBlockArguments(reader, readState.blocks[readState.curBlock], scope, argOffset);
  6495. const numBlockArgs = readState.blocks[readState.curBlock].arguments ? readState.blocks[readState.curBlock].arguments.length : 0;
  6496. if (readState.nextValueIdx !== undefined) {
  6497. readState.nextValueIdx += numBlockArgs;
  6498. }
  6499. }
  6500. }
  6501. if (readState.isIsolated) {
  6502. this.valueScopes.pop();
  6503. }
  6504. regionStack.pop();
  6505. }
  6506. parseBlockHeader(reader) {
  6507. const numOpsAndHasArgs = reader.parseVarInt();
  6508. const numOps = (numOpsAndHasArgs >> 1n).toNumber();
  6509. const hasArgs = (numOpsAndHasArgs & 1n) === 1n;
  6510. return { numOps, hasArgs };
  6511. }
  6512. parseBlockArguments(reader, block, scope, valueOffset) {
  6513. const numArgs = reader.parseVarInt().toNumber();
  6514. block.arguments = [];
  6515. for (let i = 0; i < numArgs; i++) {
  6516. let type = null;
  6517. let location = null;
  6518. if (this.version >= 4) { // kElideUnknownBlockArgLocation
  6519. const typeAndLocation = reader.parseVarInt().toNumber();
  6520. const typeIdx = typeAndLocation >> 1;
  6521. const hasLocation = (typeAndLocation & 1) === 1;
  6522. type = this.attrTypeReader.readType(typeIdx);
  6523. if (hasLocation) {
  6524. const locIdx = reader.parseVarInt().toNumber();
  6525. location = this.attrTypeReader.readAttribute(locIdx);
  6526. }
  6527. } else {
  6528. const typeIdx = reader.parseVarInt().toNumber();
  6529. type = this.attrTypeReader.readType(typeIdx);
  6530. const locIdx = reader.parseVarInt().toNumber();
  6531. location = this.attrTypeReader.readAttribute(locIdx);
  6532. }
  6533. const argName = `%${valueOffset + i}`;
  6534. const arg = new _.Value(argName, type);
  6535. arg.location = location;
  6536. block.arguments.push(arg);
  6537. if (scope && (valueOffset + i) < scope.length) {
  6538. scope[valueOffset + i] = arg;
  6539. }
  6540. }
  6541. // Use-list ordering (version >= 3) - stored after all arguments
  6542. // hasUseListOrders byte is read whenever hasArgs is true (not dependent on numArgs)
  6543. if (this.version >= 3) { // kUseListOrdering
  6544. const hasUseListOrders = reader.parseByte();
  6545. if (hasUseListOrders !== 0) {
  6546. const orders = this.parseUseListOrdersForRange(reader, numArgs);
  6547. // Store ordering information on block arguments
  6548. for (const order of orders) {
  6549. if (order.argIndex < block.arguments.length) {
  6550. block.arguments[order.argIndex].useListOrder = order.ordering;
  6551. }
  6552. }
  6553. }
  6554. }
  6555. }
  6556. parseUseListOrdersForRange(reader, numValues) {
  6557. const orders = [];
  6558. let numToRead = 1;
  6559. if (numValues > 1) {
  6560. numToRead = reader.parseVarInt().toNumber();
  6561. }
  6562. for (let i = 0; i < numToRead; i++) {
  6563. let argIndex = 0;
  6564. if (numValues > 1) {
  6565. argIndex = reader.parseVarInt().toNumber();
  6566. }
  6567. const numUsesAndFlag = reader.parseVarInt();
  6568. const numUses = (numUsesAndFlag >> 1n).toNumber();
  6569. const indexPairEncoding = (numUsesAndFlag & 1n) === 1n;
  6570. const indices = [];
  6571. for (let j = 0; j < numUses; j++) {
  6572. indices.push(reader.parseVarInt().toNumber());
  6573. }
  6574. orders.push({ argIndex, ordering: { indexPairEncoding, indices } });
  6575. }
  6576. return orders;
  6577. }
  6578. parseOpName(reader) {
  6579. const opName = reader.parseEntry(this.opNames, 'operation name');
  6580. if (!opName.opName) {
  6581. const name = `${opName.dialect.name}.${opName.name}`;
  6582. opName.opName = _.RegisteredOperationName.lookup(name, this.fileLoc.context);
  6583. if (!opName.opName) {
  6584. throw new mlir.Error(`Unregistered bytecode operation '${name}'.`);
  6585. }
  6586. }
  6587. return [opName.opName, opName.wasRegistered];
  6588. }
  6589. parseOpWithoutRegions(reader, state) {
  6590. // Parse operation name index
  6591. const [opName, wasRegistered] = this.parseOpName(reader);
  6592. const opMask = reader.parseByte();
  6593. const kHasAttrs = 0x01;
  6594. const kHasResults = 0x02;
  6595. const kHasOperands = 0x04;
  6596. const kHasSuccessors = 0x08;
  6597. const kHasInlineRegions = 0x10;
  6598. const kHasUseListOrders = 0x20;
  6599. const kHasProperties = 0x40;
  6600. const opState = new _.OperationState(null, opName);
  6601. const locIdx = reader.parseVarInt().toNumber();
  6602. opState.location = this.attrTypeReader.readAttribute(locIdx);
  6603. if (opMask & kHasAttrs) {
  6604. const dictAttrIdx = reader.parseVarInt().toNumber();
  6605. const dictAttr = this.attrTypeReader.readAttribute(dictAttrIdx);
  6606. if (dictAttr && dictAttr.value) {
  6607. if (dictAttr.value instanceof Map) {
  6608. // Already parsed as Map from custom-encoded DictionaryAttr
  6609. opState.attributes = dictAttr.value;
  6610. } else if (typeof dictAttr.value === 'string') {
  6611. // Parse dictionary attribute from ASM string format
  6612. opState.attributes = this.parseAttributeDict(dictAttr.value);
  6613. }
  6614. }
  6615. }
  6616. // Parse properties (version >= 5)
  6617. if (opMask & kHasProperties) {
  6618. if (wasRegistered) {
  6619. const dialectReader = new _.DialectReader(this.attrTypeReader, this.stringReader, this.resourceReader, this.dialectsMap, reader, this.version);
  6620. this.propertiesReader.read(this.fileLoc, dialectReader, opName, opState);
  6621. } else {
  6622. // Unregistered operations store properties as a single dictionary attribute
  6623. const propAttrIdx = reader.parseVarInt().toNumber();
  6624. const propAttr = this.attrTypeReader.readAttribute(propAttrIdx);
  6625. if (propAttr && propAttr.value) {
  6626. const propAttrs = this.parseAttributeDict(propAttr.value);
  6627. for (const [key, value] of propAttrs) {
  6628. opState.addAttribute(key, value);
  6629. }
  6630. }
  6631. }
  6632. }
  6633. // Parse results - add types to OperationState.types, track values in scope
  6634. const resultNames = [];
  6635. const resultIndices = [];
  6636. if (opMask & kHasResults) {
  6637. const numResults = reader.parseVarInt().toNumber();
  6638. const scope = this.valueScopes[this.valueScopes.length - 1];
  6639. for (let i = 0; i < numResults; i++) {
  6640. const typeIdx = reader.parseVarInt().toNumber();
  6641. const type = this.attrTypeReader.readType(typeIdx);
  6642. opState.addTypes([type]);
  6643. const valueIdx = state && state.nextValueIdx !== undefined ? state.nextValueIdx++ : scope.length;
  6644. const valueName = `%${valueIdx}`;
  6645. resultNames.push(valueName);
  6646. resultIndices.push(valueIdx);
  6647. // Create placeholder in scope (will be replaced after Operation creation with actual OpResult)
  6648. const placeholder = new _.Value(valueName, type);
  6649. if (valueIdx < scope.length) {
  6650. scope[valueIdx] = placeholder;
  6651. } else {
  6652. scope.push(placeholder);
  6653. }
  6654. }
  6655. }
  6656. if (opMask & kHasOperands) {
  6657. const numOperands = reader.parseVarInt().toNumber();
  6658. for (let i = 0; i < numOperands; i++) {
  6659. const valueIdx = reader.parseVarInt().toNumber();
  6660. const scope = this.valueScopes[this.valueScopes.length - 1];
  6661. if (valueIdx < scope.length && scope[valueIdx]) {
  6662. opState.operands.push(scope[valueIdx]);
  6663. } else {
  6664. opState.operands.push(new _.Value(`%${valueIdx}`, null));
  6665. }
  6666. }
  6667. }
  6668. if (opMask & kHasSuccessors) {
  6669. const numSuccessors = reader.parseVarInt().toNumber();
  6670. opState.successors = [];
  6671. for (let i = 0; i < numSuccessors; i++) {
  6672. const blockIdx = reader.parseVarInt().toNumber();
  6673. opState.successors.push(blockIdx);
  6674. }
  6675. }
  6676. // Parse use-list orders (version >= 3)
  6677. if (this.version >= 3 && (opMask & kHasUseListOrders)) { // kUseListOrdering
  6678. const numResults = opState.types.length;
  6679. const orders = this.parseUseListOrdersForRange(reader, numResults);
  6680. if (orders.length > 0) {
  6681. opState.useListOrders = orders;
  6682. }
  6683. }
  6684. let isIsolatedFromAbove = false;
  6685. if (opMask & kHasInlineRegions) {
  6686. const numRegionsAndIsIsolated = reader.parseVarInt();
  6687. const numRegions = (numRegionsAndIsIsolated >> 1n).toNumber();
  6688. isIsolatedFromAbove = (numRegionsAndIsIsolated & 1n) === 1n;
  6689. for (let i = 0; i < numRegions; i++) {
  6690. opState.regions.push({ blocks: [] });
  6691. }
  6692. }
  6693. return { state: opState, resultNames, isIsolatedFromAbove, resultIndices };
  6694. }
  6695. parseAttributeDict(str) {
  6696. const attrs = new Map();
  6697. // Parse dictionary attribute format: {key = value, ...}
  6698. if (!str.startsWith('{') || !str.endsWith('}')) {
  6699. return attrs;
  6700. }
  6701. const content = str.slice(1, -1).trim();
  6702. if (content.length === 0) {
  6703. return attrs;
  6704. }
  6705. let i = 0;
  6706. while (i < content.length) {
  6707. while (i < content.length && /\s/.test(content[i])) {
  6708. i++;
  6709. }
  6710. if (i >= content.length) {
  6711. break;
  6712. }
  6713. // Read key (alphanumeric/underscore)
  6714. const keyStart = i;
  6715. while (i < content.length && /[a-zA-Z0-9_]/.test(content[i])) {
  6716. i++;
  6717. }
  6718. const key = content.slice(keyStart, i);
  6719. if (!key) {
  6720. break;
  6721. }
  6722. while (i < content.length && /\s/.test(content[i])) {
  6723. i++;
  6724. }
  6725. if (i >= content.length || content[i] !== '=') {
  6726. break;
  6727. }
  6728. i++; // skip '='
  6729. while (i < content.length && /\s/.test(content[i])) {
  6730. i++;
  6731. }
  6732. // Read value (until balanced comma or end)
  6733. const valueStart = i;
  6734. let depth = 0;
  6735. let inString = false;
  6736. while (i < content.length) {
  6737. const c = content[i];
  6738. if (inString) {
  6739. if (c === '"' && content[i - 1] !== '\\') {
  6740. inString = false;
  6741. }
  6742. i++;
  6743. continue;
  6744. }
  6745. if (c === '"') {
  6746. inString = true;
  6747. i++;
  6748. continue;
  6749. }
  6750. if (c === '{' || c === '[' || c === '(' || c === '<') {
  6751. depth++;
  6752. } else if (c === '}' || c === ']' || c === ')' || c === '>') {
  6753. depth--;
  6754. } else if (c === ',' && depth === 0) {
  6755. break;
  6756. }
  6757. i++;
  6758. }
  6759. const value = content.slice(valueStart, i).trim();
  6760. attrs.set(key, { value, toString: () => value });
  6761. if (i < content.length && content[i] === ',') {
  6762. i++;
  6763. }
  6764. }
  6765. return attrs;
  6766. }
  6767. static parseDialectGrouping(reader, dialects, entryCallback) {
  6768. const dialect = reader.parseEntry(dialects, 'dialect');
  6769. const numEntries = reader.parseVarInt().toNumber();
  6770. for (let i = 0; i < numEntries; i++) {
  6771. entryCallback(dialect);
  6772. }
  6773. }
  6774. };
  6775. _.Constraint = class {
  6776. constructor(name, args, values) {
  6777. this.name = name;
  6778. this.args = args || null;
  6779. this.values = values || null;
  6780. }
  6781. static parse(value) {
  6782. const tokens = _.Constraint.tokenize(value);
  6783. const result = _.Constraint.parseTokens(tokens, 0);
  6784. const { name, args, values } = result.value;
  6785. return new _.Constraint(name, args, values);
  6786. }
  6787. toString() {
  6788. if (this.args && this.args.length > 0) {
  6789. const args = this.args.map((arg) => arg.name).join(', ');
  6790. return `${this.name}<${args}>`;
  6791. }
  6792. if (this.values && this.values.length > 0) {
  6793. return `${this.name}{${this.values.join(' | ')}}`;
  6794. }
  6795. return this.name;
  6796. }
  6797. static tokenize(str) {
  6798. const tokens = [];
  6799. let i = 0;
  6800. while (i < str.length) {
  6801. const ch = str[i];
  6802. if (/\s/.test(ch)) {
  6803. i++;
  6804. continue;
  6805. }
  6806. if ('<>={}[](),|'.indexOf(ch) !== -1) {
  6807. tokens.push({ type: ch, value: ch, pos: i });
  6808. i++;
  6809. continue;
  6810. }
  6811. if (ch === ':' && i + 1 < str.length && str[i + 1] === ':') {
  6812. tokens.push({ type: '::', value: '::', pos: i });
  6813. i += 2;
  6814. continue;
  6815. }
  6816. if (ch === ':') {
  6817. i++;
  6818. continue;
  6819. }
  6820. if (ch === '"' || ch === "'") {
  6821. const quote = ch;
  6822. let j = i + 1;
  6823. while (j < str.length && str[j] !== quote) {
  6824. if (str[j] === '\\' && j + 1 < str.length) {
  6825. j += 2;
  6826. } else {
  6827. j++;
  6828. }
  6829. }
  6830. if (j < str.length) {
  6831. tokens.push({ type: 'string', value: str.substring(i + 1, j), pos: i });
  6832. i = j + 1;
  6833. } else {
  6834. tokens.push({ type: 'ident', value: str.substring(i), pos: i });
  6835. break;
  6836. }
  6837. continue;
  6838. }
  6839. if (/[a-zA-Z_0-9-]/.test(ch)) {
  6840. let j = i;
  6841. while (j < str.length && /[a-zA-Z_0-9-]/.test(str[j])) {
  6842. j++;
  6843. }
  6844. const ident = str.substring(i, j);
  6845. tokens.push({ type: 'ident', value: ident, pos: i });
  6846. i = j;
  6847. continue;
  6848. }
  6849. i++;
  6850. }
  6851. return tokens;
  6852. }
  6853. static parseTokens(tokens, pos) {
  6854. if (pos >= tokens.length) {
  6855. return null;
  6856. }
  6857. const token = tokens[pos];
  6858. if (token.type === '::') {
  6859. let name = '';
  6860. let nextPos = pos;
  6861. while (nextPos < tokens.length) {
  6862. if (tokens[nextPos].type === '::') {
  6863. name += '::';
  6864. nextPos++;
  6865. } else if (tokens[nextPos].type === 'ident') {
  6866. name += tokens[nextPos].value;
  6867. nextPos++;
  6868. } else {
  6869. break;
  6870. }
  6871. }
  6872. if (!name) {
  6873. return null;
  6874. }
  6875. if (nextPos < tokens.length) {
  6876. const nextToken = tokens[nextPos];
  6877. if (nextToken.type === '{') {
  6878. return _.Constraint._parseEnum(tokens, pos, name);
  6879. }
  6880. if (nextToken.type === '<') {
  6881. return _.Constraint._parseGeneric(tokens, pos, name);
  6882. }
  6883. }
  6884. return { value: { name }, nextPos };
  6885. }
  6886. if (token.type !== 'ident') {
  6887. return null;
  6888. }
  6889. let name = token.value;
  6890. let nextPos = pos + 1;
  6891. while (nextPos < tokens.length && tokens[nextPos].type === '::') {
  6892. nextPos++;
  6893. if (nextPos < tokens.length && tokens[nextPos].type === 'ident') {
  6894. const value = tokens[nextPos++].value;
  6895. name += `::${value}`;
  6896. } else {
  6897. break;
  6898. }
  6899. }
  6900. if (nextPos >= tokens.length) {
  6901. return { value: { name }, nextPos };
  6902. }
  6903. const nextToken = tokens[nextPos];
  6904. if (nextToken.type === '{') {
  6905. return _.Constraint._parseEnum(tokens, pos, name);
  6906. }
  6907. if (nextToken.type === '<') {
  6908. return _.Constraint._parseGeneric(tokens, pos, name);
  6909. }
  6910. return { value: { name }, nextPos };
  6911. }
  6912. static _parseEnum(tokens, startPos, name) {
  6913. let pos = startPos;
  6914. while (pos < tokens.length && (tokens[pos].type === 'ident' || tokens[pos].type === '::')) {
  6915. pos++;
  6916. }
  6917. if (pos >= tokens.length || tokens[pos].type !== '{') {
  6918. return null;
  6919. }
  6920. pos++;
  6921. const values = [];
  6922. let currentValue = '';
  6923. while (pos < tokens.length && tokens[pos].type !== '}') {
  6924. const token = tokens[pos];
  6925. if (token.type === '|') {
  6926. if (currentValue.trim()) {
  6927. values.push(currentValue.trim());
  6928. currentValue = '';
  6929. }
  6930. pos++;
  6931. } else if (token.type === 'ident') {
  6932. if (currentValue) {
  6933. currentValue += ' ';
  6934. }
  6935. currentValue += token.value;
  6936. pos++;
  6937. } else if (token.type === '::') {
  6938. currentValue += '::';
  6939. pos++;
  6940. } else {
  6941. pos++;
  6942. }
  6943. }
  6944. if (currentValue.trim()) {
  6945. values.push(currentValue.trim());
  6946. }
  6947. if (pos < tokens.length && tokens[pos].type === '}') {
  6948. pos++;
  6949. }
  6950. return { value: { name, values }, nextPos: pos };
  6951. }
  6952. static _parseGeneric(tokens, startPos, name) {
  6953. let pos = startPos;
  6954. while (pos < tokens.length && (tokens[pos].type === 'ident' || tokens[pos].type === '::')) {
  6955. pos++;
  6956. }
  6957. if (pos >= tokens.length || tokens[pos].type !== '<') {
  6958. return null;
  6959. }
  6960. pos++;
  6961. const args = [];
  6962. let angleDepth = 1;
  6963. let bracketDepth = 0;
  6964. let currentArg = [];
  6965. while (pos < tokens.length && (angleDepth > 0 || bracketDepth > 0)) {
  6966. const token = tokens[pos];
  6967. if (token.type === '<') {
  6968. angleDepth++;
  6969. currentArg.push(token);
  6970. pos++;
  6971. } else if (token.type === '>') {
  6972. angleDepth--;
  6973. if (angleDepth === 0 && bracketDepth === 0) {
  6974. if (currentArg.length > 0) {
  6975. const parsed = _.Constraint.parseArgumentTokens(currentArg);
  6976. if (parsed !== null) {
  6977. args.push(parsed);
  6978. }
  6979. }
  6980. pos++;
  6981. break;
  6982. }
  6983. currentArg.push(token);
  6984. pos++;
  6985. } else if (token.type === '[') {
  6986. bracketDepth++;
  6987. currentArg.push(token);
  6988. pos++;
  6989. } else if (token.type === ']') {
  6990. bracketDepth--;
  6991. currentArg.push(token);
  6992. pos++;
  6993. } else if (token.type === ',' && angleDepth === 1 && bracketDepth === 0) {
  6994. if (currentArg.length > 0) {
  6995. const parsed = _.Constraint.parseArgumentTokens(currentArg);
  6996. if (parsed !== null) {
  6997. args.push(parsed);
  6998. }
  6999. currentArg = [];
  7000. }
  7001. pos++;
  7002. } else {
  7003. currentArg.push(token);
  7004. pos++;
  7005. }
  7006. }
  7007. return { value: { name, args }, nextPos: pos };
  7008. }
  7009. static parseArgumentTokens(tokens) {
  7010. if (!tokens || tokens.length === 0) {
  7011. return null;
  7012. }
  7013. tokens = tokens.filter((t) => t.type !== undefined);
  7014. if (tokens[0].type === '[') {
  7015. return _.Constraint.parseListArgument(tokens);
  7016. }
  7017. if (tokens[0].type === 'string') {
  7018. return tokens[0].value;
  7019. }
  7020. if (tokens[0].type === 'ident' || tokens[0].type === '::') {
  7021. const result = _.Constraint.parseTokens(tokens, 0);
  7022. if (result && result.nextPos === tokens.length) {
  7023. return result.value;
  7024. }
  7025. }
  7026. let literal = '';
  7027. for (const token of tokens) {
  7028. if (token.type === 'ident' || token.type === 'string') {
  7029. if (literal && !/^[,[\]():.]$/.test(literal[literal.length - 1])) {
  7030. literal += ' ';
  7031. }
  7032. literal += token.value;
  7033. } else if (token.type === '::') {
  7034. literal += '::';
  7035. } else if ('{}[](),.'.indexOf(token.type) !== -1) {
  7036. literal += token.value;
  7037. }
  7038. }
  7039. return literal.trim() || null;
  7040. }
  7041. static parseListArgument(tokens) {
  7042. if (!tokens || tokens.length === 0 || tokens[0].type !== '[') {
  7043. return null;
  7044. }
  7045. let pos = 1;
  7046. const items = [];
  7047. let bracketDepth = 1;
  7048. let angleDepth = 0;
  7049. let currentItem = [];
  7050. while (pos < tokens.length && (bracketDepth > 0 || angleDepth > 0)) {
  7051. const token = tokens[pos];
  7052. if (token.type === '[') {
  7053. bracketDepth++;
  7054. currentItem.push(token);
  7055. pos++;
  7056. } else if (token.type === ']') {
  7057. bracketDepth--;
  7058. if (bracketDepth === 0 && angleDepth === 0) {
  7059. if (currentItem.length > 0) {
  7060. const parsed = _.Constraint.parseArgumentTokens(currentItem);
  7061. if (parsed !== null) {
  7062. items.push(parsed);
  7063. }
  7064. }
  7065. break;
  7066. }
  7067. currentItem.push(token);
  7068. pos++;
  7069. } else if (token.type === '<') {
  7070. angleDepth++;
  7071. currentItem.push(token);
  7072. pos++;
  7073. } else if (token.type === '>') {
  7074. angleDepth--;
  7075. currentItem.push(token);
  7076. pos++;
  7077. } else if (token.type === ',' && bracketDepth === 1 && angleDepth === 0) {
  7078. if (currentItem.length > 0) {
  7079. const parsed = _.Constraint.parseArgumentTokens(currentItem);
  7080. if (parsed !== null) {
  7081. items.push(parsed);
  7082. }
  7083. currentItem = [];
  7084. }
  7085. pos++;
  7086. } else {
  7087. currentItem.push(token);
  7088. pos++;
  7089. }
  7090. }
  7091. return items;
  7092. }
  7093. };
  7094. _.AssemblyFormatParser = class {
  7095. constructor(metadata) {
  7096. this._metadata = metadata;
  7097. this._buffer = metadata.assemblyFormat || '';
  7098. this._pos = 0;
  7099. }
  7100. match(char) {
  7101. return this._pos < this._buffer.length && this._buffer[this._pos] === char;
  7102. }
  7103. accept(str) {
  7104. if (str.length === 1) {
  7105. if (this.match(str)) {
  7106. this._pos++;
  7107. return true;
  7108. }
  7109. return false;
  7110. }
  7111. const remaining = this._buffer.substring(this._pos);
  7112. if (remaining.startsWith(str)) {
  7113. // Check that keyword is not followed by alphanumeric (to avoid "type" in "typename")
  7114. const nextChar = this._buffer[this._pos + str.length];
  7115. if (nextChar && /[a-zA-Z0-9_-]/.test(nextChar)) {
  7116. return false;
  7117. }
  7118. this._pos += str.length;
  7119. return true;
  7120. }
  7121. return false;
  7122. }
  7123. expect(char) {
  7124. if (!this.match(char)) {
  7125. throw new mlir.Error(`Expected '${char}'.`);
  7126. }
  7127. this._pos++;
  7128. }
  7129. parse() {
  7130. const directives = [];
  7131. this._skipWhitespace();
  7132. while (this._pos < this._buffer.length) {
  7133. const directive = this.parseDirective();
  7134. directives.push(directive);
  7135. this._skipWhitespace();
  7136. }
  7137. return directives;
  7138. }
  7139. parseDirective() {
  7140. const ch = this._buffer[this._pos];
  7141. if (!ch || this._pos >= this._buffer.length) {
  7142. throw new mlir.Error(`Unexpected end of format string.`);
  7143. }
  7144. // Parenthesized group: can be optional (...)? or conditional (...):(...) or just grouping (...)
  7145. if (this.match('(')) {
  7146. this.accept('(');
  7147. const elements = [];
  7148. let anchorElement = null;
  7149. this._skipWhitespace();
  7150. while (!this.match(')')) {
  7151. const elem = this.parseDirective();
  7152. if (elem.type === 'anchor') {
  7153. // Standalone anchor - applies to the previous element
  7154. if (elements.length > 0) {
  7155. const prev = elements[elements.length - 1];
  7156. anchorElement = prev.name || prev.type;
  7157. }
  7158. } else {
  7159. if (elem.anchor) {
  7160. anchorElement = elem.name || elem.type;
  7161. }
  7162. elements.push(elem);
  7163. }
  7164. this._skipWhitespace();
  7165. }
  7166. this.expect(')');
  7167. this._skipWhitespace();
  7168. // Check what follows to determine the group type
  7169. if (this.accept('?')) {
  7170. // Optional group: (...)?
  7171. return { type: 'optional_group', elements, anchor: anchorElement };
  7172. }
  7173. if (this.accept(':')) {
  7174. // Conditional alternative: (...):(...)?
  7175. this._skipWhitespace();
  7176. const secondAlt = [];
  7177. let isSecondOptional = false;
  7178. if (this.accept('(')) {
  7179. this._skipWhitespace();
  7180. while (!this.match(')')) {
  7181. const elem = this.parseDirective();
  7182. secondAlt.push(elem);
  7183. this._skipWhitespace();
  7184. }
  7185. this.expect(')');
  7186. this._skipWhitespace();
  7187. if (this.accept('?')) {
  7188. isSecondOptional = true;
  7189. }
  7190. }
  7191. return { type: 'conditional_alternative', firstAlt: elements, secondAlt, secondOptional: isSecondOptional };
  7192. }
  7193. return { type: 'group', elements };
  7194. }
  7195. // Literal: `keyword`
  7196. if (this.accept('`')) {
  7197. const value = this.parseUntil('`');
  7198. this.expect('`');
  7199. // MLIR reference: Empty literals (`` or ` `) are whitespace, not literals
  7200. if (value.length === 0 || value === ' ' || value === '\\n') {
  7201. return { type: 'whitespace', value }; // Return whitespace as a directive
  7202. }
  7203. return { type: 'literal', value };
  7204. }
  7205. if (this.accept('$')) {
  7206. const name = this.parseIdentifier();
  7207. const anchor = this.accept('^');
  7208. const metadata = this._metadata;
  7209. // Determine variable type from metadata first - matches reference implementation
  7210. // Check each metadata category in priority order
  7211. if (metadata.successors && metadata.successors.some((a) => a.name === name)) {
  7212. return { type: 'successor_ref', name, anchor };
  7213. }
  7214. if (metadata.attributes && metadata.attributes.some((a) => a.name === name)) {
  7215. return { type: 'attribute_ref', name, anchor };
  7216. }
  7217. if (metadata.operands && metadata.operands.some((a) => a.name === name)) {
  7218. return { type: 'operand_ref', name, anchor };
  7219. }
  7220. if (metadata.regions && metadata.regions.some((a) => a.name === name)) {
  7221. return { type: 'region_ref', name, anchor };
  7222. }
  7223. throw new mlir.Error(`Unknown variable '$${name}' in assembly format.`);
  7224. }
  7225. if (this.accept('type')) {
  7226. const args = this.parseParenList();
  7227. const anchor = this.accept('^');
  7228. return { type: 'type', args, anchor };
  7229. }
  7230. if (this.accept('qualified')) {
  7231. const args = this.parseParenList();
  7232. const anchor = this.accept('^');
  7233. return { type: 'qualified', args, anchor };
  7234. }
  7235. if (this.accept('attr-dict-with-keyword')) {
  7236. return { type: 'attr_dict_with_keyword' };
  7237. }
  7238. if (this.accept('attr-dict')) {
  7239. return { type: 'attr_dict' };
  7240. }
  7241. if (this.accept('prop-dict')) {
  7242. return { type: 'prop_dict' };
  7243. }
  7244. if (this.accept('functional-type')) {
  7245. const args = this.parseParenList();
  7246. const anchor = this.accept('^');
  7247. return { type: 'functional_type', args, anchor };
  7248. }
  7249. if (this.accept('params')) {
  7250. return { type: 'params' };
  7251. }
  7252. if (this.accept('struct')) {
  7253. this.expect('(');
  7254. const args = [];
  7255. while (!this.match(')')) {
  7256. this._skipWhitespace();
  7257. if (this.match(')')) {
  7258. break;
  7259. }
  7260. const arg = this.parseDirective();
  7261. args.push(arg);
  7262. this._skipWhitespace();
  7263. this.accept(',');
  7264. }
  7265. this.expect(')');
  7266. return { type: 'struct', args };
  7267. }
  7268. if (this.accept('ref')) {
  7269. this.expect('(');
  7270. const arg = this.parseDirective();
  7271. this._skipWhitespace();
  7272. this.expect(')');
  7273. return { type: 'ref', arg };
  7274. }
  7275. if (this.accept('custom')) {
  7276. this.expect('<');
  7277. const parser = this.parseUntil('>');
  7278. this.expect('>');
  7279. const args = this.parseParenList();
  7280. const anchor = this.accept('^');
  7281. return { type: 'custom', parser, args, anchor };
  7282. }
  7283. if (this.accept('oilist')) {
  7284. this._skipWhitespace();
  7285. this.expect('(');
  7286. let content = '';
  7287. let depth = 1;
  7288. while (this._pos < this._buffer.length && depth > 0) {
  7289. const ch = this._buffer[this._pos];
  7290. if (ch === '(') {
  7291. depth++;
  7292. content += ch;
  7293. this._pos++;
  7294. } else if (ch === ')') {
  7295. depth--;
  7296. if (depth > 0) {
  7297. content += ch;
  7298. }
  7299. this._pos++;
  7300. } else {
  7301. content += ch;
  7302. this._pos++;
  7303. }
  7304. }
  7305. return { type: 'oilist', content };
  7306. }
  7307. if (this.accept('operands')) {
  7308. return { type: 'operands' };
  7309. }
  7310. if (this.accept('results')) {
  7311. return { type: 'results' };
  7312. }
  7313. if (this.accept('regions')) {
  7314. return { type: 'regions' };
  7315. }
  7316. if (this.accept('successors')) {
  7317. return { type: 'successors' };
  7318. }
  7319. if (ch === '^') {
  7320. this._pos++;
  7321. return { type: 'anchor' };
  7322. }
  7323. if (/^[:()[\]{}<>,=|]/.test(ch)) {
  7324. this._pos++;
  7325. return { type: 'literal', value: ch };
  7326. }
  7327. const context = this._buffer.substring(Math.max(0, this._pos - 10), Math.min(this._buffer.length, this._pos + 10));
  7328. throw new mlir.Error(`Unexpected '${ch}' in assembly format '${context}...'.`);
  7329. }
  7330. parseIdentifier() {
  7331. let name = '';
  7332. while (this._pos < this._buffer.length) {
  7333. const ch = this._buffer[this._pos];
  7334. if (/[a-zA-Z0-9_]/.test(ch)) {
  7335. name += ch;
  7336. this._pos++;
  7337. } else {
  7338. break;
  7339. }
  7340. }
  7341. return name;
  7342. }
  7343. parseUntil(terminator) {
  7344. let value = '';
  7345. while (this._pos < this._buffer.length && this._buffer[this._pos] !== terminator) {
  7346. value += this._buffer[this._pos];
  7347. this._pos++;
  7348. }
  7349. return value;
  7350. }
  7351. parseParenList() {
  7352. this._skipWhitespace();
  7353. if (!this.accept('(')) {
  7354. return [];
  7355. }
  7356. this._skipWhitespace();
  7357. if (this.accept(')')) {
  7358. return [];
  7359. }
  7360. const items = [];
  7361. const parseElement = () => {
  7362. let element = '';
  7363. let depth = 0;
  7364. while (this._pos < this._buffer.length) {
  7365. this._skipWhitespace();
  7366. if (this.accept('"')) {
  7367. // String literal - consume as a unit
  7368. element += '"';
  7369. element += this.parseUntil('"');
  7370. element += '"';
  7371. this.expect('"');
  7372. } else if (this.accept('$')) {
  7373. element += '$';
  7374. const id = this.parseIdentifier();
  7375. element += id;
  7376. } else if (this.accept('(')) {
  7377. // Nested parentheses - include in element (e.g., type($list))
  7378. element += '(';
  7379. depth++;
  7380. } else if (this.match(')')) {
  7381. if (depth === 0) {
  7382. // End of this element
  7383. break;
  7384. }
  7385. element += ')';
  7386. this.accept(')');
  7387. depth--;
  7388. } else if (this.match(',') && depth === 0) {
  7389. // Comma at top level - end of this element
  7390. break;
  7391. } else if (this.match('-')) {
  7392. // Handle hyphenated identifiers like attr-dict, functional-type
  7393. element += '-';
  7394. this.accept('-');
  7395. } else {
  7396. // Plain identifier (e.g., "type" in type($list))
  7397. const id = this.parseIdentifier();
  7398. if (!id) {
  7399. throw new mlir.Error(`Unexpected '${this._buffer[this._pos]}' in assembly format directive list.`);
  7400. }
  7401. element += id;
  7402. }
  7403. }
  7404. return element.trim();
  7405. };
  7406. const first = parseElement();
  7407. if (!first) {
  7408. throw new mlir.Error('Expected element.');
  7409. }
  7410. items.push(first);
  7411. this._skipWhitespace();
  7412. while (this.accept(',')) {
  7413. this._skipWhitespace();
  7414. const elem = parseElement();
  7415. if (!elem) {
  7416. throw new mlir.Error('Expected element after comma');
  7417. }
  7418. items.push(elem);
  7419. this._skipWhitespace();
  7420. }
  7421. this.expect(')');
  7422. return items;
  7423. }
  7424. _skipWhitespace() {
  7425. while (this._pos < this._buffer.length && /\s/.test(this._buffer[this._pos])) {
  7426. this._pos++;
  7427. }
  7428. }
  7429. };
  7430. _.DialectContext = class {
  7431. constructor(metadata) {
  7432. const operations = metadata.operations;
  7433. this._dialects = new Map();
  7434. this._dialects.set('builtin', new _.BuiltinDialect(operations));
  7435. this._dialects.set('std', new _.Dialect(operations, 'std'));
  7436. this._dialects.set('bufferization', new _.BufferizationDialect(operations));
  7437. this._dialects.set('stablehlo', new _.StableHLODialect(operations));
  7438. this._dialects.set('vhlo', new _.VhloDialect(operations));
  7439. this._dialects.set('interpreter', new _.InterpreterDialect(operations));
  7440. this._dialects.set('affine', new _.AffineDialect(operations));
  7441. this._dialects.set('asuka', new _.AsukaDialect(operations));
  7442. this._dialects.set('arith', new _.ArithDialect(operations));
  7443. this._dialects.set('async', new _.async.AsyncDialect(operations));
  7444. this._dialects.set('cf', new _.CFDialect(operations));
  7445. this._dialects.set('emitc', new _.EmitCDialect(operations));
  7446. this._dialects.set('complex', new _.Dialect(operations, 'complex'));
  7447. this._dialects.set('index', new _.Dialect(operations, 'index'));
  7448. this._dialects.set('pdl', new _.pdl.PDLDialect(operations));
  7449. this._dialects.set('ptr', new _.ptr.PtrDialect(operations));
  7450. this._dialects.set('ub', new _.Dialect(operations, 'ub'));
  7451. this._dialects.set('amdgpu', new _.AMDGPUDialect(operations));
  7452. this._dialects.set('nvgpu', new _.NVGPUDialect(operations));
  7453. this._dialects.set('nvvm', new _.NVVMDialect(operations));
  7454. this._dialects.set('rocdl', new _.ROCDLDialect(operations));
  7455. this._dialects.set('nvws', new _.NVWSDialect(operations));
  7456. this._dialects.set('tti', new _.Dialect(operations, 'tti'));
  7457. this._dialects.set('omp', new _.OpenMPDialect(operations));
  7458. this._dialects.set('proton', new _.ProtonDialect(operations));
  7459. this._dialects.set('proton_gpu', new _.Dialect(operations, 'proton_gpu'));
  7460. this._dialects.set('arm_sme', new _.ArmSMEDialect(operations));
  7461. this._dialects.set('arm_neon', new _.ArmNeonDialect(operations));
  7462. this._dialects.set('arm_sve', new _.ArmSVEDialect(operations));
  7463. this._dialects.set('shard', new _.ShardDialect(operations));
  7464. this._dialects.set('amx', new _.Dialect(operations, 'amx'));
  7465. this._dialects.set('smt', new _.smt.SMTDialect(operations));
  7466. this._dialects.set('lagrad', new _.Dialect(operations, 'lagrad'));
  7467. this._dialects.set('iree_codegen', new _.IREECodegenDialect(operations));
  7468. this._dialects.set('iree_encoding', new _.Dialect(operations, 'iree_encoding'));
  7469. this._dialects.set('test', new _.TestDialect(operations));
  7470. this._dialects.set('scf', new _.SCFDialect(operations));
  7471. this._dialects.set('shape', new _.ShapeDialect(operations));
  7472. this._dialects.set('sparse_tensor', new _.SparseTensorDialect(operations));
  7473. this._dialects.set('func', new _.FuncDialect(operations));
  7474. this._dialects.set('gpu', new _.GpuDialect(operations));
  7475. this._dialects.set('llvm', new _.LLVM.LLVMDialect(operations));
  7476. this._dialects.set('xegpu', new _.XeGPUDialect(operations));
  7477. this._dialects.set('memref', new _.MemRefDialect(operations));
  7478. this._dialects.set('vector', new _.VectorDialect(operations));
  7479. this._dialects.set('x86vector', new _.Dialect(operations, 'x86vector'));
  7480. this._dialects.set('onnx', new _.ONNXDialect(operations));
  7481. this._dialects.set('krnl', new _.KrnlDialect(operations));
  7482. this._dialects.set('torch', new _.TorchDialect(operations));
  7483. this._dialects.set('torch_c', new _.Dialect(operations, 'torch_c'));
  7484. this._dialects.set('hal', new _.HALDialect(operations));
  7485. this._dialects.set('hal_loader', new _.HALLoaderDialect(operations));
  7486. this._dialects.set('hal_inline', new _.Dialect(operations, 'hal_inline'));
  7487. this._dialects.set('util', new _.UtilDialect(operations));
  7488. this._dialects.set('mhlo', new _.MhloDialect(operations));
  7489. this._dialects.set('chlo', new _.ChloDialect(operations));
  7490. this._dialects.set('thlo', new _.THLODialect(operations));
  7491. this._dialects.set('flow', new _.FlowDialect(operations));
  7492. this._dialects.set('stream', new _.StreamDialect(operations));
  7493. this._dialects.set('iree_vector_ext', new _.IREEVectorExtDialect(operations));
  7494. this._dialects.set('iree_tensor_ext', new _.IREETensorExtDialect(operations));
  7495. this._dialects.set('linalg', new _.LinalgDialect(operations));
  7496. this._dialects.set('iree_linalg_ext', new _.Dialect(operations, 'iree_linalg_ext'));
  7497. this._dialects.set('linalg_ext', this._dialects.get('iree_linalg_ext'));
  7498. this._dialects.set('quant', new _.QuantDialect(operations));
  7499. this._dialects.set('tensor', new _.TensorDialect(operations));
  7500. this._dialects.set('tosa', new _.TosaDialect(operations));
  7501. this._dialects.set('tf', new _.TFDialect(operations));
  7502. this._dialects.set('tf_saved_model', new _.Dialect(operations, 'tf_saved_model'));
  7503. this._dialects.set('tf_type', new _.TFTypeDialect(operations));
  7504. this._dialects.set('tf_device', new _.TFDeviceDialect(operations));
  7505. this._dialects.set('tf_executor', new _.TFExecutorDialect(operations));
  7506. this._dialects.set('tf_framework', new _.TFFrameworkDialect(operations));
  7507. this._dialects.set('tfr', new _.TFRDialect(operations));
  7508. this._dialects.set('corert', new _.CoreRTDialect(operations));
  7509. this._dialects.set('tfrt', new _.TFRTDialect(operations));
  7510. this._dialects.set('tfrt_fallback', new _.Dialect(operations, 'tfrt_fallback'));
  7511. this._dialects.set('tfrt_fallback_async', new _.TFRTFallbackAsyncDialect(operations));
  7512. this._dialects.set('tfl', new _.TFLDialect(operations));
  7513. this._dialects.set('stdx', new _.StdxDialect(operations));
  7514. this._dialects.set('vm', new _.VMDialect(operations));
  7515. this._dialects.set('math', new _.MathDialect(operations));
  7516. this._dialects.set('tm_tensor', new _.TMTensorDialect(operations));
  7517. this._dialects.set('ml_program', new _.MLProgramDialect(operations));
  7518. this._dialects.set('iree_gpu', new _.IREEGPUDialect(operations));
  7519. this._dialects.set('tile', new _.TileDialect(operations));
  7520. this._dialects.set('pxa', new _.PXADialect(operations));
  7521. this._dialects.set('irdl', new _.IRDLDialect(operations));
  7522. this._dialects.set('transform', new _.TransformDialect(operations));
  7523. this._dialects.set('wasmssa', new _.WasmSSADialect(operations));
  7524. this._dialects.set('spirv', new _.spirv.SPIRVDialect(operations));
  7525. this._dialects.set('spv', this._dialects.get('spirv'));
  7526. this._dialects.set('toy', new _.ToyDialect(operations));
  7527. this._dialects.set('top', new _.Dialect(operations, 'top'));
  7528. this._dialects.set('tpu', new _.Dialect(operations, 'tpu'));
  7529. this._dialects.set('sdfg', new _.SdfgDialect(operations));
  7530. this._dialects.set('sdir', this._dialects.get('sdfg'));
  7531. this._dialects.set('check', new _.Dialect(operations, 'check'));
  7532. this._dialects.set('tt', new _.triton.TritonDialect(operations));
  7533. this._dialects.set('ttg', new _.triton.gpu.TritonGPUDialect(operations));
  7534. this._dialects.set('triton_gpu', this._dialects.get('ttg'));
  7535. this._dialects.set('gluon', new _.GluonDialect(operations));
  7536. this._dialects.set('ttng', new _.TritonNvidiaGPUDialect(operations));
  7537. this._dialects.set('nvidia_gpu', this._dialects.get('ttng'));
  7538. this._dialects.set('amdg', new _.TritonAMDGPUDialect(operations));
  7539. this._dialects.set('amd_gpu', this._dialects.get('amdg'));
  7540. this._dialects.set('michelson', new _.MichelsonDialect(operations));
  7541. this._dialects.set('tensorrt', new _.TensorRTDialect(operations));
  7542. this._dialects.set('executor', new _.executor.ExecutorDialect(operations));
  7543. this._dialects.set('exec', this._dialects.get('executor'));
  7544. this._dialects.set('tfrt_test', new _.TFRTTestDialect(operations));
  7545. this._dialects.set('xevm', new _.XeVMDialect(operations));
  7546. this._dialects.set('vmvx', new _.VMVXDialect(operations));
  7547. this._dialects.set('mlrt', new _.MLRTDialect(operations));
  7548. this._dialects.set('tfrt_tensor', new _.TFRTTensorDialect(operations));
  7549. this._dialects.set('tfrt_dht', new _.TFRTDHTDialect(operations));
  7550. this._dialects.set('coo', new _.Dialect(operations, 'coo'));
  7551. this._dialects.set('tfd', new _.TFDDialect(operations));
  7552. this._dialects.set('acc', new _.ACCDialect(operations));
  7553. this._dialects.set('cuda', new _.Dialect(operations, 'cuda'));
  7554. this._dialects.set('trtrt', new _.Dialect(operations, 'trtrt'));
  7555. this._dialects.set('plan', new _.PlanDialect(operations));
  7556. this._dialects.set('kernel', new _.KernelDialect(operations));
  7557. this._dialects.set('nvg', new _.Dialect(operations, 'nvg'));
  7558. this._dialects.set('mpi', new _.Dialect(operations, 'mpi'));
  7559. this._dialects.set('pdl_interp', new _.PDLInterpDialect(operations));
  7560. this._dialects.set('standalone', new _.Dialect(operations, 'standalone'));
  7561. this._dialects.set('custom', new _.Dialect(operations, 'custom'));
  7562. this._dialects.set('layer', new _.Dialect(operations, 'layer'));
  7563. this._dialects.set('foo', new _.Dialect(operations, 'foo'));
  7564. this._dialects.set('some', new _.Dialect(operations, 'some'));
  7565. this._dialects.set('ts', new _.Dialect(operations, 'ts'));
  7566. this._dialects.set('tf_mlrt', new _.Dialect(operations, 'tf_mlrt'));
  7567. this._dialects.set('io_parameters', new _.IOParametersDialect(operations));
  7568. this._dialects.set('pcf', new _.PCFDialect(operations));
  7569. this._dialects.set('linalgx', new _.Dialect(operations, 'linalgx'));
  7570. this._dialects.set('xsmm', new _.XSMMDialect(operations));
  7571. this._dialects.set('sdy', new _.SdyDialect(operations));
  7572. this._dialects.set('mpmd', new _.MPMDDialect(operations));
  7573. this._dialects.set('tfg', new _.TFGDialect(operations));
  7574. this._dialects.set('vt', new _.Dialect(operations, 'vt'));
  7575. this._dialects.set('testd', new _.Dialect(operations, 'testd'));
  7576. this._dialects.set('cmath', new _.Dialect(operations, 'cmath'));
  7577. this._dialects.set('bytecode', new _.Dialect(operations, 'bytecode'));
  7578. this._dialects.set('test_irdl_to_cpp', new _.Dialect(operations, 'test_irdl_to_cpp'));
  7579. this._dialects.set('iree_unregistered', new _.Dialect(operations, 'iree_unregistered'));
  7580. this._dialects.set('cir', new _.Dialect(operations, 'cir'));
  7581. this._dialects.set('migraphx', new _.Dialect(operations, 'migraphx'));
  7582. this._dialects.set('xla', new _.XlaDialect(operations));
  7583. this._dialects.set('xla_gpu', new _.XlaGpuDialect(operations));
  7584. this._dialects.set('xla_cpu', new _.Dialect(operations, 'xla_cpu'));
  7585. this._dialects.set('xla_framework', new _.Dialect(operations, 'xla_framework'));
  7586. this._dialects.set('ifrt', new _.Dialect(operations, 'ifrt'));
  7587. this._dialects.set('vifrt', new _.Dialect(operations, 'vifrt'));
  7588. this._dialects.set('nir', new _.Dialect(operations, 'nir'));
  7589. this._dialects.set('triton_xla', new _.TritonXlaDialect(operations));
  7590. this._dialects.set('xtile', new _.XTileDialect(operations));
  7591. this._dialects.set('xten_nn', new _.XtenNNDialect(operations));
  7592. this._dialects.set('ensemble', new _.EnsembleDialect(operations));
  7593. this._dialects.set('poly', new _.PolyDialect(operations));
  7594. this._dialects.set('noisy', new _.NoisyDialect(operations));
  7595. this._dialects.set('plugin', new _.Dialect(operations, 'plugin'));
  7596. this._dialects.set('ttcore', new _.Dialect(operations, 'ttcore'));
  7597. this._dialects.set('ttir', new _.Dialect(operations, 'ttir'));
  7598. this._dialects.set('ttnn', new _.Dialect(operations, 'ttnn'));
  7599. this._dialects.set('ttkernel', new _.Dialect(operations, 'ttkernel'));
  7600. this._dialects.set('ttmetal', new _.Dialect(operations, 'ttmetal'));
  7601. }
  7602. getOrLoadDialect(name) {
  7603. return this._dialects.get(name);
  7604. }
  7605. getLoadedDialect(name) {
  7606. return this._dialects.has(name);
  7607. }
  7608. checkDialect(dialect, dialectName, context) {
  7609. if (!dialect) {
  7610. switch (dialectName) {
  7611. case 'bstnnx':
  7612. case 'common':
  7613. case 'dxgml':
  7614. case 'dxgml_pattern':
  7615. case 'gim':
  7616. case 'nir':
  7617. case 'nn':
  7618. case 'torq_hl':
  7619. case 'xir':
  7620. case 'xth':
  7621. throw new mlir.Error(`Undocumented ${context} dialect '${dialectName}'.`);
  7622. default:
  7623. throw new mlir.Error(`Unsupported ${context} dialect '${dialectName}'.`);
  7624. }
  7625. }
  7626. }
  7627. redirect(name) {
  7628. return this._redirect.has(name) ? this._redirect.get(name) : name;
  7629. }
  7630. };
  7631. _.Dialect = class {
  7632. constructor(operations, name) {
  7633. this._name = name;
  7634. this._operations = new Map();
  7635. this._customDirectives = new Map();
  7636. this._customTypes = new Map();
  7637. this._customAttributes = new Map();
  7638. this.registerCustomDirective('DynamicIndexList', this.parseDynamicIndexList.bind(this));
  7639. this.registerCustomDirective('Offsets', this.parseOffsets.bind(this));
  7640. this.registerCustomDirective('SymbolVisibility', this.parseSymbolVisibility.bind(this));
  7641. this.registerCustomDirective('TypeOrAttr', this.parseTypeOrAttr.bind(this));
  7642. this.registerCustomDirective('CopyOpRegion', this.parseCopyOpRegion.bind(this));
  7643. this.registerCustomDirective('SizeAwareType', this.parseSizeAwareType.bind(this));
  7644. this.registerCustomDirective('ResultTypeList', this.parseResultTypeList.bind(this));
  7645. this.registerCustomDirective('CmdParameterGatherOperations', this.parseCmdParameterGatherOperations.bind(this));
  7646. this.registerCustomDirective('AsyncParameterGatherOperations', this.parseAsyncParameterGatherOperations.bind(this));
  7647. this.registerCustomDirective('CmdParameterScatterOperations', this.parseCmdParameterScatterOperations.bind(this));
  7648. this.registerCustomDirective('AsyncParameterScatterOperations', this.parseAsyncParameterScatterOperations.bind(this));
  7649. this.registerCustomAttribute('TypedAttrInterface', this.parseTypedAttrInterface.bind(this));
  7650. this.registerCustomAttribute('VM_ConstantIntegerValueAttr', this.parseTypedAttrInterface.bind(this));
  7651. this.registerCustomAttribute('Util_AnySerializableAttr', this.parseTypedAttrInterface.bind(this));
  7652. this.registerCustomAttribute('ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7653. this.registerCustomAttribute('DenseElementsAttr', this.parseTypedAttrInterface.bind(this));
  7654. this.registerCustomAttribute('I32ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7655. this.registerCustomAttribute('I64ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7656. this.registerCustomAttribute('F64ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7657. this.registerCustomAttribute('IndexElementsAttr', this.parseTypedAttrInterface.bind(this));
  7658. this.registerCustomAttribute('AnyI32ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7659. this.registerCustomAttribute('AnyIntElementsAttr', this.parseTypedAttrInterface.bind(this));
  7660. this.registerCustomAttribute('StringElementsAttr', this.parseTypedAttrInterface.bind(this));
  7661. this.registerCustomAttribute('RankedF32ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7662. this.registerCustomAttribute('RankedF64ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7663. this.registerCustomAttribute('RankedI32ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7664. this.registerCustomAttribute('RankedI64ElementsAttr', this.parseTypedAttrInterface.bind(this));
  7665. this.registerCustomAttribute('SignlessIntElementsAttr', this.parseTypedAttrInterface.bind(this));
  7666. this.registerCustomAttribute('AnyAttr', this.parseTypedAttrInterface.bind(this));
  7667. this.registerCustomAttribute('UnitAttr', this.parseUnitAttr.bind(this));
  7668. this.registerCustomAttribute('UnitProp', this.parseUnitAttr.bind(this));
  7669. this.registerCustomAttribute('SymbolNameAttr', this.parseSymbolNameAttr.bind(this));
  7670. this.registerCustomAttribute('SymbolRefAttr', this.parseSymbolRefAttr.bind(this));
  7671. this.registerCustomAttribute('FlatSymbolRefAttr', this.parseFlatSymbolRefAttr.bind(this));
  7672. this.registerCustomAttribute('OptionalAttr', this.parseOptionalAttr.bind(this));
  7673. this.registerCustomAttribute('OptionalProp', this.parseOptionalAttr.bind(this));
  7674. this.registerCustomAttribute('DefaultValuedOptionalAttr', this.parseDefaultValuedOptionalAttr.bind(this));
  7675. this.registerCustomAttribute('DefaultValuedAttr', this.parseDefaultValuedAttr.bind(this));
  7676. this.registerCustomAttribute('DefaultValuedEnumAttr', this.parseDefaultValuedAttr.bind(this));
  7677. this.registerCustomAttribute('DefaultValuedProp', this.parseDefaultValuedAttr.bind(this));
  7678. this.registerCustomAttribute('ConfinedAttr', this.parseConfinedAttr.bind(this));
  7679. this.registerCustomAttribute('IntValidAlignment', this.parseConfinedAttr.bind(this));
  7680. this.registerCustomAttribute('TypeAttrOf', this.parseTypeAttrOf.bind(this));
  7681. this.registerCustomAttribute('AnyAttrOf', this.parseAnyAttrOf.bind(this));
  7682. this.registerCustomAttribute('ArrayAttr', this.parseArrayAttr.bind(this));
  7683. this.registerCustomAttribute('TypedArrayAttrBase', this.parseArrayAttr.bind(this));
  7684. this.registerCustomAttribute('DenseI64ArrayAttr', _.DenseI64ArrayAttr.parse);
  7685. this.registerCustomAttribute('I64Attr', (parser) => parser.parseAttribute(new _.IntegerType('i64')));
  7686. this.registerCustomAttribute('I32Attr', (parser) => parser.parseAttribute(new _.IntegerType('i32')));
  7687. this.registerCustomAttribute('I16Attr', (parser) => parser.parseAttribute(new _.IntegerType('i16')));
  7688. this.registerCustomAttribute('I8Attr', (parser) => parser.parseAttribute(new _.IntegerType('i8')));
  7689. this.registerCustomAttribute('I1Attr', (parser) => parser.parseAttribute(new _.IntegerType('i1')));
  7690. this.registerCustomAttribute('SI64Attr', (parser) => parser.parseAttribute(new _.IntegerType('si64')));
  7691. this.registerCustomAttribute('SI32Attr', (parser) => parser.parseAttribute(new _.IntegerType('si32')));
  7692. this.registerCustomAttribute('UI64Attr', (parser) => parser.parseAttribute(new _.IntegerType('ui64')));
  7693. this.registerCustomAttribute('UI32Attr', (parser) => parser.parseAttribute(new _.IntegerType('ui32')));
  7694. this.registerCustomAttribute('IndexAttr', (parser) => parser.parseAttribute(new _.IntegerType('index')));
  7695. this.registerCustomAttribute('I64Prop', (parser) => parser.parseAttribute(new _.IntegerType('i64')));
  7696. this.registerCustomAttribute('I32Prop', (parser) => parser.parseAttribute(new _.IntegerType('i32')));
  7697. this.registerCustomAttribute('AlignmentProp', (parser) => parser.parseAttribute(new _.IntegerType('i64')));
  7698. this.registerCustomAttribute('F64Attr', (parser) => parser.parseAttribute(new _.FloatType('f64')));
  7699. this.registerCustomAttribute('F32Attr', (parser) => parser.parseAttribute(new _.FloatType('f32')));
  7700. this.registerCustomAttribute('F16Attr', (parser) => parser.parseAttribute(new _.FloatType('f16')));
  7701. this.registerCustomAttribute('BF16Attr', (parser) => parser.parseAttribute(new _.FloatType('bf16')));
  7702. this.registerCustomAttribute('StrAttr', (parser) => parser.parseAttribute(new _.PrimitiveType('string')));
  7703. this.registerCustomAttribute('TypedStrAttr', this.parseTypedAttrInterface.bind(this));
  7704. this.registerCustomAttribute('LevelAttr', (parser) => parser.parseAttribute(new _.IntegerType('index')));
  7705. this.registerCustomType('Optional', this.parseOptional.bind(this));
  7706. for (const metadata of operations.get(name) || []) {
  7707. this.registerOperandName(metadata.name, metadata);
  7708. }
  7709. }
  7710. get name() {
  7711. return this._name;
  7712. }
  7713. readType(/* reader */) {
  7714. throw new mlir.Error(`Bytecode dialect '${this._name}' does not support bytecode types.`);
  7715. }
  7716. readAttribute(/* reader */) {
  7717. throw new mlir.Error(`Dialect '${this._name}' does not support bytecode attributes.`);
  7718. }
  7719. parseResource(/* entry */) {
  7720. throw new mlir.Error(`Dialect '${this._name}' does not support resources.`);
  7721. }
  7722. getOperation(opName) {
  7723. const op = this._operations.get(opName);
  7724. if (op && !op.metadata._) {
  7725. if (Array.isArray(op.metadata.operands)) {
  7726. for (const input of op.metadata.operands) {
  7727. if (input && input.type) {
  7728. input.type = _.Constraint.parse(input.type);
  7729. }
  7730. }
  7731. }
  7732. if (Array.isArray(op.metadata.results)) {
  7733. for (const output of op.metadata.results) {
  7734. if (output && output.type) {
  7735. output.type = _.Constraint.parse(output.type);
  7736. }
  7737. }
  7738. }
  7739. if (Array.isArray(op.metadata.attributes)) {
  7740. for (const attribute of op.metadata.attributes) {
  7741. if (attribute && attribute.type) {
  7742. attribute.type = _.Constraint.parse(attribute.type);
  7743. }
  7744. }
  7745. }
  7746. if (Array.isArray(op.metadata.regions)) {
  7747. for (const region of op.metadata.regions) {
  7748. if (region && region.type) {
  7749. region.type = _.Constraint.parse(region.type);
  7750. }
  7751. }
  7752. }
  7753. if (Array.isArray(op.metadata.traits)) {
  7754. for (const trait of op.metadata.traits) {
  7755. if (trait && trait.type) {
  7756. trait.type = _.Constraint.parse(trait.type);
  7757. }
  7758. }
  7759. }
  7760. op.metadata._ = true;
  7761. }
  7762. return op || null;
  7763. }
  7764. registerOperandName(opName, metadata) {
  7765. const opInfo = new _.RegisteredOperationName(this, opName, metadata);
  7766. this._operations.set(opName, opInfo);
  7767. }
  7768. registerCustomDirective(name, parserFn) {
  7769. this._customDirectives.set(name, parserFn);
  7770. }
  7771. registerCustomType(name, parserFn) {
  7772. this._customTypes.set(name, parserFn);
  7773. }
  7774. registerCustomAttribute(name, parserFn) {
  7775. this._customAttributes.set(name, parserFn);
  7776. }
  7777. createBuildableType(constraint) {
  7778. switch (constraint.name) {
  7779. case 'AMDGPU_TDMDescriptorType': return new _.Type('!amdgpu.tdm.descriptor');
  7780. case 'AnyIRModule': return new _.Type('!transform.any_op');
  7781. case 'AnySignlessIntegerOrIndex': return new _.IndexType();
  7782. case 'Async_CoroHandleType': return new _.Type('!async.coro.handle');
  7783. case 'Async_CoroIdType': return new _.Type('!async.coro.id');
  7784. case 'Async_CoroStateType': return new _.Type('!async.coro.state');
  7785. case 'Async_GroupType': return new _.async.GroupType();
  7786. case 'Async_TokenType': return new _.async.TokenType();
  7787. case 'Async_ValueType': return new _.async.ValueType(new _.MemRefType([-1], new _.Type('f32')));
  7788. case 'BF16': return new _.Type('bf16');
  7789. case 'BoolType': return new _.Type('!smt.bool');
  7790. case 'CanonicalLoopInfoType': return new _.Type('!omp.canonical_loop_info');
  7791. case 'ControlType': return new _.Type('!tf_type.control');
  7792. case 'CoreRT_OpHandlerType': return new _.Type('!corert.ophandler');
  7793. case 'CoreRT_StringType': return new _.Type('!corert.string');
  7794. case 'CoreRT_TensorHandleType': return new _.Type('!corert.tensorhandle');
  7795. case 'CUDA_BlasGemmAlgorithm': return new _.Type('!cuda.blas.gemm_algorithm');
  7796. case 'CUDA_BlasHandle': return new _.Type('!cuda.blas.handle');
  7797. case 'CUDA_Device': return new _.Type('!cuda.device');
  7798. case 'CUDA_Event': return new _.Type('!cuda.event');
  7799. case 'CUDA_Function': return new _.Type('!cuda.function');
  7800. case 'CUDA_Module': return new _.Type('!cuda.module');
  7801. case 'CUDA_Stream': return new _.Type('!cuda.stream');
  7802. case 'EmitC_PointerType': return new _.Type('!emitc.ptr<i32>');
  7803. case 'Executor_HostPtr': return new _.Type('!executor.ptr<host>');
  7804. case 'Executor_StrLiteral': return new _.Type('!executor.str_literal');
  7805. case 'Executor_Table': return new _.Type('!executor.table<>');
  7806. case 'F128': return new _.Type('f128');
  7807. case 'F16': return new _.Type('f16');
  7808. case 'F32': return new _.Type('f32');
  7809. case 'F4E2M1FN': return new _.Type('f4E2M1FN');
  7810. case 'F64': return new _.Type('f64');
  7811. case 'F6E2M3FN': return new _.Type('f6E2M3FN');
  7812. case 'F6E3M2FN': return new _.Type('f6E3M2FN');
  7813. case 'F80': return new _.Type('f80');
  7814. case 'F8E3M4': return new _.Type('f8E3M4');
  7815. case 'F8E4M3': return new _.Type('f8E4M3');
  7816. case 'F8E4M3B11FNUZ': return new _.Type('f8E4M3B11FNUZ');
  7817. case 'F8E4M3FN': return new _.Type('f8E4M3FN');
  7818. case 'F8E4M3FNUZ': return new _.Type('f8E4M3FNUZ');
  7819. case 'F8E5M2': return new _.Type('f8E5M2');
  7820. case 'F8E5M2FNUZ': return new _.Type('f8E5M2FNUZ');
  7821. case 'F8E8M0FNU': return new _.Type('f8E8M0FNU');
  7822. case 'FLOW_Channel': return new _.Type('!flow.channel');
  7823. case 'GPU_AsyncToken': return new _.Type('!gpu.async.token');
  7824. case 'GPU_SparseDnTensorHandle': return new _.Type('!gpu.sparse.dntensor_handle');
  7825. case 'GPU_SparseSpGEMMOpHandle': return new _.Type('!gpu.sparse.spgemmop_handle');
  7826. case 'GPU_SparseSpMatHandle': return new _.Type('!gpu.sparse.spmat_handle');
  7827. case 'HostBufferType': return new _.Type('!tfrt_ht.host_buffer');
  7828. case 'I1': return new _.IntegerType('i1');
  7829. case 'I128': return new _.IntegerType('i128');
  7830. case 'I16': return new _.IntegerType('i16');
  7831. case 'I32': return new _.IntegerType('i32');
  7832. case 'I64': return new _.IntegerType('i64');
  7833. case 'I8': return new _.IntegerType('i8');
  7834. case 'Ifrt_ArrayType': return new _.Type('!ifrt.array');
  7835. case 'Ifrt_ControlType': return new _.Type('!ifrt.control');
  7836. case 'Index': return new _.IndexType();
  7837. case 'IntType': return new _.Type('!smt.int');
  7838. case 'IRDL_AttributeType': return new _.Type('!irdl.attribute');
  7839. case 'IRDL_RegionType': return new _.Type('!irdl.region');
  7840. case 'IREE_Input_GlobalRefAttr': return new _.Type('!iree_input.global.ref');
  7841. case 'LLVM_DefaultPointer': return new _.Type('!llvm.ptr');
  7842. case 'LLVM_PointerGeneric': return new _.Type('!llvm.ptr');
  7843. case 'LLVM_PointerGlobal': return new _.Type('!llvm.ptr<1>');
  7844. case 'LLVM_PointerShared': return new _.Type('!llvm.ptr<3>');
  7845. case 'LLVM_PointerSharedCluster': return new _.Type('!llvm.ptr<7>');
  7846. case 'LLVM_PointerTensor': return new _.Type('!llvm.ptr<6>');
  7847. case 'LLVM_PointerTensorMemory': return new _.Type('!llvm.ptr<6>');
  7848. case 'LLVM_TokenType': return new _.Type('!llvm.token');
  7849. case 'MLProgram_TokenType': return new _.Type('!ml_program.token');
  7850. case 'MlrtAsyncHandleType': return new _.Type('!mlrt.async_handle');
  7851. case 'MlrtFutureType': return new _.Type('!mlrt.future');
  7852. case 'MlrtPromiseType': return new _.Type('!mlrt.promise');
  7853. case 'MPI_Comm': return new _.Type('!mpi.comm');
  7854. case 'MPI_Request': return new _.Type('!mpi.request');
  7855. case 'MPI_Retval': return new _.Type('!mpi.retval');
  7856. case 'Noisy_I32': return new _.Type('!noisy.i32');
  7857. case 'NoneType': return new _.Type('none');
  7858. case 'NullPointer': return new _.Type('!iree_codegen.null_pointer');
  7859. case 'NVGPU_DeviceAsyncToken': return new _.Type('!nvgpu.device.async.token');
  7860. case 'NVGPU_MmaSparseSyncMetadataType': return new _.VectorType([2], new _.IntegerType('i16'));
  7861. case 'OMP_MapBoundsType': return new _.Type('!omp.map.bounds');
  7862. case 'OpaqueTensorType': return new _.Type('!tf_type.tensor');
  7863. case 'OpenACC_DataBoundsType': return new _.Type('!acc.data_bounds');
  7864. case 'OpenACC_DeclareTokenType': return new _.Type('!acc.declare_token');
  7865. case 'OpenMP_MapBoundsType': return new _.Type('!omp.map.bounds');
  7866. case 'PDL_Attribute': return new _.pdl.AttributeType();
  7867. case 'PDL_Operation': return new _.pdl.OperationType();
  7868. case 'PDL_OperationType': return new _.pdl.OperationType();
  7869. case 'PDL_RangeOf': return new _.pdl.RangeType(this.createBuildableType(constraint.args[0]));
  7870. case 'PDL_RangeType': return new _.Type('!pdl.range<type>');
  7871. case 'PDL_Type': return new _.pdl.TypeType();
  7872. case 'PDL_TypeType': return new _.pdl.TypeType();
  7873. case 'PDL_Value': return new _.pdl.ValueType();
  7874. case 'PDL_ValueType': return new _.pdl.ValueType();
  7875. case 'Ptr_PtrType': return new _.Type('!ptr.ptr');
  7876. case 'ROCDL_V16BF16Type': return new _.VectorType([16], new _.Type('bf16'));
  7877. case 'ROCDL_V16F16Type': return new _.VectorType([16], new _.Type('f16'));
  7878. case 'ROCDL_V16F32Type': return new _.VectorType([16], new _.Type('f32'));
  7879. case 'ROCDL_V2BF16Type': return new _.VectorType([2], new _.Type('bf16'));
  7880. case 'ROCDL_V2F16Type': return new _.VectorType([2], new _.Type('f16'));
  7881. case 'ROCDL_V2F32Type': return new _.VectorType([2], new _.Type('f32'));
  7882. case 'ROCDL_V2I16Type': return new _.VectorType([2], new _.IntegerType('i16'));
  7883. case 'ROCDL_V2I32Type': return new _.VectorType([2], new _.IntegerType('i32'));
  7884. case 'ROCDL_V32BF16Type': return new _.VectorType([32], new _.Type('bf16'));
  7885. case 'ROCDL_V32F16Type': return new _.VectorType([32], new _.Type('f16'));
  7886. case 'ROCDL_V32F32Type': return new _.VectorType([32], new _.Type('f32'));
  7887. case 'ROCDL_V3I32Type': return new _.VectorType([3], new _.IntegerType('i32'));
  7888. case 'ROCDL_V6I32Type': return new _.VectorType([6], new _.IntegerType('i32'));
  7889. case 'ROCDL_V8BF16Type': return new _.VectorType([8], new _.Type('bf16'));
  7890. case 'ROCDL_V8F16Type': return new _.VectorType([8], new _.Type('f16'));
  7891. case 'ROCDL_V8F32Type': return new _.VectorType([8], new _.Type('f32'));
  7892. case 'Shape_ExtentTensorType': return new _.Type('tensor<?xindex>');
  7893. case 'Shape_ShapeType': return new _.Type('!shape.shape');
  7894. case 'Shape_SizeType': return new _.Type('!shape.size');
  7895. case 'Shape_ValueShapeType': return new _.Type('!shape.value_shape');
  7896. case 'Shape_WitnessType': return new _.Type('!shape.witness');
  7897. case 'StaticShapeTensorOf': return new _.UnrankedTensorType(this.createBuildableType(constraint.args[0][0]));
  7898. case 'SI16': return new _.IntegerType('si16');
  7899. case 'SI32': return new _.IntegerType('si32');
  7900. case 'SI64': return new _.IntegerType('si64');
  7901. case 'SI8': return new _.IntegerType('si8');
  7902. case 'SMTFuncType': return new _.Type('!smt.func<() -> ()>');
  7903. case 'SPIRV_AnyPtr': return new _.Type('!spirv.ptr<i32, StorageBuffer>');
  7904. case 'SPIRV_BFloat16KHR': return new _.FloatType('bf16');
  7905. case 'SPIRV_Bool': return new _.IntegerType('i1');
  7906. case 'SPIRV_Float16': return new _.FloatType('f16');
  7907. case 'SPIRV_Float32': return new _.FloatType('f32');
  7908. case 'SPIRV_Int8': return new _.IntegerType('i8');
  7909. case 'SPIRV_Int16': return new _.IntegerType('i16');
  7910. case 'SPIRV_Int32': return new _.IntegerType('i32');
  7911. case 'SPIRV_Int32Vec4': return new _.VectorType([4], new _.IntegerType('i32'));
  7912. case 'Stream_Channel': return new _.Type('!stream.channel');
  7913. case 'Stream_Dim': return new _.IndexType();
  7914. case 'Stream_Offset': return new _.IndexType();
  7915. case 'Stream_Size': return new _.IndexType();
  7916. case 'TensorRTRuntime_Context': return new _.Type('!trtrt.context');
  7917. case 'TensorRTRuntime_Engine': return new _.Type('!trtrt.engine');
  7918. case 'TensorType': return new _.Type('!tfrt_tensor.tensor');
  7919. case 'TF_MLRT_FutureType': return new _.Type('!tf_mlrt.tensor');
  7920. case 'TF32': return new _.Type('tf32');
  7921. case 'TFAllocatorType': return new _.Type('!tfrt_fallback.tf_allocator');
  7922. case 'TFDeviceType': return new _.Type('!tf_mlrt.device');
  7923. case 'TfeControlType': return new _.Type('!tfe.control');
  7924. case 'TfeTokenType': return new _.Type('!tfe.token');
  7925. case 'TFFramework_JITCallableType': return new _.Type('!tf_framework.jit_callable');
  7926. case 'TFFramework_OpKernelContextType': return new _.Type('!tf_framework.op_kernel_context');
  7927. case 'TFL_Control': return new _.Type('!tfl.control');
  7928. case 'TFL_Quint8': return new _.Type('!quant.uniform<u8:f32, 1.0>');
  7929. case 'TFL_Str': return new _.Type('!tf.string');
  7930. case 'TFR_AttrType': return new _.Type('!tfr.attr');
  7931. case 'TFR_TensorListType': return new _.Type('!tfr.tensor_list');
  7932. case 'TFR_TensorType': return new _.Type('!tfr.tensor');
  7933. case 'TFRT_ChainType': return new _.Type('!tfrt.chain');
  7934. case 'TFRT_DeviceType': return new _.Type('!tfrt.device');
  7935. case 'TFRT_Fallback_TFTensorType': return new _.Type('!tfrt_fallback.tf_tensor');
  7936. case 'TFRT_StringType': return new _.Type('!tfrt.string');
  7937. case 'TFRT_TensorTypeType': return new _.Type('!tfrt.tensor_type');
  7938. case 'TFTensorType': return new _.Type('!tfrt_fallback.tf_tensor');
  7939. case 'Torch_BoolType': return new _.Type('!torch.bool');
  7940. case 'Torch_DeviceType': return new _.Type('!torch.Device');
  7941. case 'Torch_FloatType': return new _.Type('!torch.float');
  7942. case 'Torch_GeneratorType': return new _.Type('!torch.Generator');
  7943. case 'Torch_IntType': return new _.Type('!torch.int');
  7944. case 'Torch_LinearParamsType': return new _.Type('!torch.LinearParams');
  7945. case 'Torch_NoneType': return new _.Type('!torch.none');
  7946. case 'Torch_NumberType': return new _.Type('!torch.number');
  7947. case 'Torch_StringType': return new _.Type('!torch.str');
  7948. case 'Transform_AffineMapParamType': return new _.Type('!transform.affine_map');
  7949. case 'Transform_AnyOpType': return new _.Type('!transform.any_op');
  7950. case 'Transform_AnyParamType': return new _.Type('!transform.any_param');
  7951. case 'Transform_AnyValue': return new _.Type('!transform.any_value');
  7952. case 'Transform_AnyValueType': return new _.Type('!transform.any_value');
  7953. case 'Transform_ParamType': return new _.Type('!transform.param<i64>');
  7954. case 'Transform_TypeParamType': return new _.Type('!transform.type');
  7955. case 'TransformHandleTypeInterface': return new _.Type('!transform.any_op');
  7956. case 'TestTransformTestDialectParamType': return new _.Type('!transform.test_dialect_param');
  7957. case 'TS_FixedRankShape': return new _.OpaqueType('ts', `.fixed_rank_shape.${constraint.args[0].name}`);
  7958. case 'TS_PartialShape': return new _.Type('!ts.partial_shape');
  7959. case 'TS_Shape': return new _.Type('!ts.shape');
  7960. case 'TTG_AsyncToken': return new _.Type('!ttg.async.token');
  7961. case 'UI16': return new _.IntegerType('ui16');
  7962. case 'UI32': return new _.IntegerType('ui32');
  7963. case 'UI64': return new _.IntegerType('ui64');
  7964. case 'UI8': return new _.IntegerType('ui8');
  7965. case 'Util_BufferType': return new _.Type('!util.buffer');
  7966. case 'Util_Offset': return new _.IndexType();
  7967. case 'Util_Size': return new _.IndexType();
  7968. case 'VM_CondValue': return new _.IntegerType('i32');
  7969. case 'VM_RefType': return new _.Type('!vm.ref<?>');
  7970. case 'XeGPU_Nbarrier': return new _.Type('!xegpu.nbarrier');
  7971. case 'XLA_BufferType': return new _.Type('!xla_framework.buffer');
  7972. case 'XLAFramework_BufferType': return new _.Type('!xla_framework.buffer');
  7973. default: return null;
  7974. }
  7975. }
  7976. inferResultTypes(op, vars) {
  7977. const metadata = op.name.getRegisteredInfo()?.metadata;
  7978. if (!metadata?.results) {
  7979. return;
  7980. }
  7981. // If type(results) was used in the format, all result types were explicitly parsed
  7982. if (vars.has('results') && vars.get('results').types.length > 0) {
  7983. if (op.types.length === 0) {
  7984. op.addTypes(vars.get('results').types);
  7985. }
  7986. return;
  7987. }
  7988. const operandNames = metadata.operands?.map((o) => o.name) || [];
  7989. // Build result types in metadata order
  7990. const orderedTypes = [];
  7991. // Track current offset in op.types for custom directive handling
  7992. let customDirectiveOffset = 0;
  7993. // Iterate over each result in metadata order
  7994. for (const resultInfo of metadata.results) {
  7995. // If this result was parsed from assembly format, use those types
  7996. if (vars.has(resultInfo.name) && vars.get(resultInfo.name).types.length > 0) {
  7997. const varTypes = vars.get(resultInfo.name).types;
  7998. orderedTypes.push(...varTypes);
  7999. customDirectiveOffset += varTypes.length;
  8000. continue;
  8001. }
  8002. const typeName = typeof resultInfo.type === 'string' ? resultInfo.type : resultInfo.type?.name;
  8003. const isVariadicOrOptional = typeName === 'Variadic' || typeName === 'Optional';
  8004. // For Variadic/Optional not in vars, check if custom directive added types to op.types
  8005. if (isVariadicOrOptional && op.types.length > customDirectiveOffset) {
  8006. // Count how many types belong to this variadic result
  8007. // (all types from customDirectiveOffset to end, minus types for later results in vars)
  8008. let typesForLaterResults = 0;
  8009. for (let i = metadata.results.indexOf(resultInfo) + 1; i < metadata.results.length; i++) {
  8010. const laterResult = metadata.results[i];
  8011. if (vars.has(laterResult.name) && vars.get(laterResult.name).types.length > 0) {
  8012. typesForLaterResults += vars.get(laterResult.name).types.length;
  8013. }
  8014. }
  8015. const variadicCount = op.types.length - customDirectiveOffset - typesForLaterResults;
  8016. if (variadicCount > 0) {
  8017. for (let i = 0; i < variadicCount; i++) {
  8018. orderedTypes.push(op.types[customDirectiveOffset + i]);
  8019. }
  8020. customDirectiveOffset += variadicCount;
  8021. continue;
  8022. }
  8023. }
  8024. // Try to resolve from traits
  8025. let resolved = false;
  8026. if (metadata.traits) {
  8027. for (const trait of metadata.traits) {
  8028. if (resolved) {
  8029. break;
  8030. }
  8031. // Handle both string and object trait types
  8032. const traitName = trait.type?.name;
  8033. const traitArgs = trait.type?.args;
  8034. // SameOperandsAndResultType: result type = first operand type
  8035. if (traitName === 'SameOperandsAndResultType') {
  8036. if (op.operands.length > 0 && op.operands[0].type) {
  8037. orderedTypes.push(op.operands[0].type);
  8038. resolved = true;
  8039. }
  8040. }
  8041. // AllTypesMatch: result type = matched operand/result/attribute type
  8042. if (traitName === 'AllTypesMatch') {
  8043. const names = traitArgs?.[0];
  8044. if (Array.isArray(names) && (names.includes(resultInfo.name) || (resultInfo.name === 'result' && names.includes('result')))) {
  8045. const sourceTypes = [];
  8046. for (const argName of names) {
  8047. if (argName === resultInfo.name) {
  8048. continue;
  8049. }
  8050. // Check if source is in vars (another parsed result)
  8051. if (vars.get(argName) && vars.get(argName).types.length > 0) {
  8052. sourceTypes.push(...vars.get(argName).types);
  8053. break;
  8054. }
  8055. // Check if source is an operand
  8056. const operandMetaIdx = operandNames.indexOf(argName);
  8057. if (operandMetaIdx >= 0) {
  8058. const operandMeta = metadata.operands[operandMetaIdx];
  8059. const operandTypeObj = operandMeta?.type;
  8060. const operandTypeName = typeof operandTypeObj === 'string' ? operandTypeObj : (operandTypeObj?.name || '');
  8061. const isVariadic = operandTypeName === 'Variadic' || operandTypeName.startsWith('Variadic<');
  8062. if (isVariadic) {
  8063. for (let j = 0; j < op.operands.length; j++) {
  8064. if (op.operands[j].type) {
  8065. sourceTypes.push(op.operands[j].type);
  8066. }
  8067. }
  8068. } else if (operandMetaIdx < op.operands.length && op.operands[operandMetaIdx].type) {
  8069. sourceTypes.push(op.operands[operandMetaIdx].type);
  8070. }
  8071. if (sourceTypes.length > 0) {
  8072. break;
  8073. }
  8074. }
  8075. // Check if source is an attribute with a type
  8076. if (metadata.attributes) {
  8077. const attrMeta = metadata.attributes.find((a) => a.name === argName);
  8078. if (attrMeta) {
  8079. const attr = op.attributes.get(argName);
  8080. if (attr && attr.type) {
  8081. sourceTypes.push(attr.type);
  8082. break;
  8083. }
  8084. }
  8085. }
  8086. }
  8087. if (sourceTypes.length > 0) {
  8088. orderedTypes.push(...sourceTypes);
  8089. resolved = true;
  8090. }
  8091. }
  8092. }
  8093. // TypesMatchWith: result type = transform(source type)
  8094. if (traitName === 'TypesMatchWith') {
  8095. const [lhsArg, rhsArg, transformer] = traitArgs || [];
  8096. let resultArg = null;
  8097. let sourceArg = null;
  8098. if ((rhsArg === resultInfo.name || (resultInfo.name === 'result' && rhsArg === 'result'))) {
  8099. resultArg = rhsArg;
  8100. sourceArg = lhsArg;
  8101. } else if ((lhsArg === resultInfo.name || (resultInfo.name === 'result' && lhsArg === 'result'))) {
  8102. resultArg = lhsArg;
  8103. sourceArg = rhsArg;
  8104. }
  8105. if (resultArg && sourceArg) {
  8106. const sourceTypes = [];
  8107. // Check if source is in vars (parsed result or operand type from type($var))
  8108. if (vars.has(sourceArg) && vars.get(sourceArg).types.length > 0) {
  8109. sourceTypes.push(...vars.get(sourceArg).types);
  8110. }
  8111. // Check if source is an operand - fall back to operand's value type
  8112. if (sourceTypes.length === 0) {
  8113. const operands = metadata.operands || [];
  8114. let actualOperandIdx = 0;
  8115. for (let i = 0; i < operands.length; i++) {
  8116. const operandTypeObj = operands[i].type;
  8117. const operandType = typeof operandTypeObj === 'string' ? operandTypeObj : (operandTypeObj?.name || '');
  8118. const isEnum = /\{[^}]+\}/.test(operandType) || operandType.startsWith('AtomicBinOp') || operandType.startsWith('AtomicOrdering') || operandType.startsWith('LLVM_AtomicOrdering') || operandType.includes('Enum');
  8119. if (operands[i].name === sourceArg) {
  8120. const isVariadicSource = operandType === 'Variadic';
  8121. if (isVariadicSource) {
  8122. for (let j = actualOperandIdx; j < op.operands.length; j++) {
  8123. if (op.operands[j].type) {
  8124. sourceTypes.push(op.operands[j].type);
  8125. }
  8126. }
  8127. } else if (actualOperandIdx < op.operands.length && op.operands[actualOperandIdx].type) {
  8128. sourceTypes.push(op.operands[actualOperandIdx].type);
  8129. }
  8130. break;
  8131. }
  8132. if (!isEnum) {
  8133. actualOperandIdx++;
  8134. }
  8135. }
  8136. }
  8137. if (sourceTypes.length > 0) {
  8138. for (const sourceType of sourceTypes) {
  8139. let resultType = sourceType;
  8140. if (transformer === '::getI1SameShape($_self)') {
  8141. if (sourceType instanceof _.VectorType) {
  8142. resultType = new _.VectorType(sourceType.dimensions, new _.IntegerType('i1'), sourceType.scalableDims);
  8143. } else if (sourceType instanceof mlir.TensorType) {
  8144. resultType = new mlir.TensorType(sourceType.dimensions, new _.IntegerType('i1'));
  8145. } else {
  8146. resultType = new _.IntegerType('i1');
  8147. }
  8148. } else if (transformer && transformer.includes('.getElementType()')) {
  8149. if (sourceType && sourceType.elementType) {
  8150. resultType = sourceType.elementType;
  8151. } else {
  8152. throw new mlir.Error(`Cannot get element type.`);
  8153. }
  8154. } else if (transformer && transformer.includes('getPointeeType')) {
  8155. if (sourceType && sourceType.pointeeType) {
  8156. resultType = sourceType.pointeeType;
  8157. } else {
  8158. throw new mlir.Error(`Cannot get pointee type.`);
  8159. }
  8160. } else if (transformer && transformer.includes('getValAndBoolStructType')) {
  8161. const typeStr = sourceType.toString ? sourceType.toString() : String(sourceType);
  8162. resultType = new _.Type(`!llvm.struct<(${typeStr}, i1)>`);
  8163. } else if (transformer && transformer.includes('.getResults()')) {
  8164. // Extract results from a FunctionType
  8165. if (sourceType instanceof _.FunctionType && sourceType.results) {
  8166. orderedTypes.push(...sourceType.results);
  8167. resolved = true;
  8168. continue; // Already added results, skip single push below
  8169. }
  8170. }
  8171. if (resultType) {
  8172. orderedTypes.push(resultType);
  8173. resolved = true;
  8174. }
  8175. }
  8176. }
  8177. }
  8178. }
  8179. // FirstAttrDerivedResultType: result type = first attribute's type
  8180. if (traitName === 'FirstAttrDerivedResultType') {
  8181. const firstAttr = metadata.attributes?.[0];
  8182. if (firstAttr) {
  8183. const attr = op.attributes.get(firstAttr.name);
  8184. if (attr && attr.type) {
  8185. orderedTypes.push(attr.type);
  8186. resolved = true;
  8187. }
  8188. }
  8189. }
  8190. }
  8191. }
  8192. // For single variadic result matching single variadic operand with same element type, infer from operands
  8193. if (!resolved && resultInfo.type?.name === 'Variadic' &&
  8194. metadata.results?.length === 1 && metadata.operands?.length === 1) {
  8195. const resultElementType = resultInfo.type.args?.[0]?.name;
  8196. const operandInfo = metadata.operands[0];
  8197. if (operandInfo.type?.name === 'Variadic' &&
  8198. operandInfo.type.args?.[0]?.name === resultElementType) {
  8199. for (const operand of op.operands) {
  8200. if (operand.type) {
  8201. orderedTypes.push(operand.type);
  8202. }
  8203. }
  8204. resolved = orderedTypes.length > 0;
  8205. }
  8206. }
  8207. // Fallback: try buildable type (skip for variadic/optional)
  8208. if (!resolved && resultInfo.type && !isVariadicOrOptional) {
  8209. const type = this.createBuildableType(resultInfo.type);
  8210. if (type) {
  8211. orderedTypes.push(type);
  8212. }
  8213. }
  8214. }
  8215. // Replace op.types with correctly ordered types
  8216. if (orderedTypes.length > 0) {
  8217. op.types.length = 0;
  8218. op.addTypes(orderedTypes);
  8219. }
  8220. }
  8221. parseDirective(directive, parser, op, opInfo, directives, i, vars) {
  8222. const isVariadic = (type) => {
  8223. if (type.name === 'Variadic' || type.name === 'VariadicOfVariadic') {
  8224. return true;
  8225. }
  8226. if (Array.isArray(type.args) && type.args.length > 0) {
  8227. return isVariadic(type.args[0]);
  8228. }
  8229. return false;
  8230. };
  8231. const isVariadicOfVariadic = (type) => {
  8232. if (type.name === 'VariadicOfVariadic') {
  8233. return true;
  8234. }
  8235. if (Array.isArray(type.args) && type.args.length > 0) {
  8236. return isVariadicOfVariadic(type.args[0]);
  8237. }
  8238. return false;
  8239. };
  8240. const isOptional = (type) => {
  8241. if (type.name === 'Optional') {
  8242. return true;
  8243. }
  8244. if (Array.isArray(type.args) && type.args.length > 0) {
  8245. return isOptional(type.args[0]);
  8246. }
  8247. return false;
  8248. };
  8249. switch (directive.type) {
  8250. case 'whitespace':
  8251. // Skip whitespace directives - they're just formatting hints
  8252. break;
  8253. case 'literal':
  8254. // Make '[' optional when followed by a variadic operand with buildable type
  8255. if (directive.value === '[' && parser.getToken().isNot(_.Token.l_square)) {
  8256. const nextDir = directives[i + 1];
  8257. if (nextDir && nextDir.type === 'operand_ref') {
  8258. const operandMeta = opInfo.metadata?.operands?.find((o) => o.name === nextDir.name);
  8259. if (operandMeta && isVariadic(operandMeta.type)) {
  8260. // Skip '[' and mark to skip ']' later
  8261. vars.set('_skipClosingBracket', true);
  8262. break;
  8263. }
  8264. }
  8265. }
  8266. if (directive.value === ']' && vars.get('_skipClosingBracket')) {
  8267. vars.delete('_skipClosingBracket');
  8268. break;
  8269. }
  8270. parser.consumeToken();
  8271. break;
  8272. case 'region_ref': {
  8273. const regionMeta = opInfo.metadata && opInfo.metadata.regions && opInfo.metadata.regions.find((r) => r.name === directive.name);
  8274. const isVariadicRegion = regionMeta && regionMeta.type && regionMeta.type.name === 'VariadicRegion';
  8275. const isIsolated = op.name.getRegisteredInfo().hasTrait('IsolatedFromAbove');
  8276. if (isVariadicRegion) {
  8277. if (parser.getToken().is(_.Token.l_brace)) {
  8278. do {
  8279. const region = op.addRegion();
  8280. parser.parseRegion(region, undefined, isIsolated);
  8281. } while (parser.parseOptionalComma() && parser.getToken().is(_.Token.l_brace));
  8282. }
  8283. } else {
  8284. const region = op.addRegion();
  8285. parser.parseRegion(region, undefined, isIsolated);
  8286. }
  8287. break;
  8288. }
  8289. case 'successor_ref': {
  8290. if (!op.successors) {
  8291. op.successors = [];
  8292. }
  8293. // Check if this successor is variadic from metadata or context
  8294. const refName = directive.name;
  8295. let isVariadicSuccessor = false;
  8296. if (opInfo.metadata && opInfo.metadata.successors) {
  8297. const successorMeta = opInfo.metadata.successors.find((s) => s.name === refName);
  8298. if (successorMeta && successorMeta.type) {
  8299. // Check for VariadicSuccessor type
  8300. const typeStr = typeof successorMeta.type === 'string' ? successorMeta.type : successorMeta.type.name;
  8301. isVariadicSuccessor = typeStr && typeStr.startsWith('VariadicSuccessor');
  8302. }
  8303. }
  8304. // Also check context: if next directive is ')' literal, we're inside parentheses
  8305. const nextDir = i + 1 < directives.length ? directives[i + 1] : null;
  8306. const isVariadicContext = isVariadicSuccessor || (nextDir && nextDir.type === 'literal' && nextDir.value === ')');
  8307. // Check if next directive is a custom directive that handles the parentheses (like ResultTypeList)
  8308. const nextDirHandlesParens = nextDir && nextDir.type === 'custom' &&
  8309. (nextDir.parser === 'ResultTypeList' || nextDir.parser === 'TypeList');
  8310. const parseOneSuccessor = () => {
  8311. const successor = {};
  8312. successor.label = parser.getToken().getSpelling().str();
  8313. parser.consumeToken(_.Token.caret_identifier);
  8314. // Don't consume '(' if next directive handles it (e.g., custom<ResultTypeList>)
  8315. if (!nextDirHandlesParens && parser.parseOptionalLParen()) {
  8316. successor.arguments = [];
  8317. while (parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.r_paren)) {
  8318. if (parser.getToken().is(_.Token.percent_identifier)) {
  8319. successor.arguments.push(parser.parseOperand());
  8320. parser.parseOptionalComma();
  8321. } else {
  8322. break;
  8323. }
  8324. }
  8325. parser.resolveOperands(successor.arguments, parser.parseOptionalColonTypeList());
  8326. parser.parseOptionalRParen();
  8327. }
  8328. op.successors.push(successor);
  8329. };
  8330. if (isVariadicContext) {
  8331. // Variadic successors: parse 0 or more successors
  8332. while (parser.getToken().is(_.Token.caret_identifier)) {
  8333. parseOneSuccessor();
  8334. if (!parser.parseOptionalComma()) {
  8335. break;
  8336. }
  8337. }
  8338. } else {
  8339. parseOneSuccessor();
  8340. }
  8341. break;
  8342. }
  8343. case 'attribute_ref': {
  8344. const refName = directive.name;
  8345. if (op.attributes.has(refName)) {
  8346. break;
  8347. }
  8348. const attrInfo = opInfo.metadata && opInfo.metadata.attributes && opInfo.metadata.attributes.find((attr) => attr.name === refName);
  8349. const attrType = attrInfo ? attrInfo.type : null;
  8350. let attrValue = null;
  8351. // Pass type to suppress : type suffix parsing (it's a separate directive in assembly format)
  8352. if (attrType && attrType !== 'Attribute') {
  8353. attrValue = this.parseCustomAttributeWithFallback(parser, attrType);
  8354. } else {
  8355. attrValue = parser.parseAttribute(attrType || 'Attribute');
  8356. }
  8357. if (attrValue) {
  8358. op.addAttribute(refName, attrValue);
  8359. }
  8360. break;
  8361. }
  8362. case 'operand_ref': {
  8363. const name = directive.name;
  8364. const input = opInfo.metadata?.operands?.find((inp) => inp.name === name);
  8365. const isVariadicOp = input ? isVariadic(input.type) : false;
  8366. const isVariadicOfVariadicOp = input ? isVariadicOfVariadic(input.type) : false;
  8367. const isOptionalOp = input ? isOptional(input.type) : false;
  8368. // Check for buildable types using createType
  8369. let buildableType = null;
  8370. if (isVariadicOp && input?.type?.args?.[0]) {
  8371. buildableType = this.createBuildableType(input.type.args[0]);
  8372. } else if (input?.type) {
  8373. buildableType = this.createBuildableType(input.type);
  8374. }
  8375. if (!vars.has(name)) {
  8376. vars.set(name, { operands: [], types: [] });
  8377. }
  8378. const entry = vars.get(name);
  8379. if (isVariadicOfVariadicOp) {
  8380. // Parse grouped operands: (op, op), (), (op)
  8381. do {
  8382. if (!parser.parseOptionalLParen()) {
  8383. break;
  8384. }
  8385. while (parser.getToken().is(_.Token.percent_identifier)) {
  8386. entry.operands.push(parser.parseOperand());
  8387. if (!parser.parseOptionalComma()) {
  8388. break;
  8389. }
  8390. }
  8391. parser.parseRParen();
  8392. } while (parser.parseOptionalComma());
  8393. } else if (isVariadicOp) {
  8394. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.r_square) && parser.getToken().isNot(_.Token.r_brace) && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace) && parser.getToken().isNot(_.Token.equal)) {
  8395. if (parser.getToken().is(_.Token.percent_identifier)) {
  8396. entry.operands.push(parser.parseOperand());
  8397. if (buildableType) {
  8398. entry.types.push(buildableType);
  8399. }
  8400. if (!parser.parseOptionalComma()) {
  8401. break;
  8402. }
  8403. } else if (buildableType && (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus))) {
  8404. // Handle integer literals for buildable integer types (e.g., I32)
  8405. let value = '';
  8406. if (parser.consumeIf(_.Token.minus)) {
  8407. value = '-';
  8408. }
  8409. value += parser.getToken().getSpelling().str();
  8410. parser.consumeToken(_.Token.integer);
  8411. entry.operands.push({ name: value, literal: true });
  8412. if (buildableType) {
  8413. entry.types.push(buildableType);
  8414. }
  8415. if (!parser.parseOptionalComma()) {
  8416. break;
  8417. }
  8418. } else {
  8419. break;
  8420. }
  8421. }
  8422. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  8423. entry.operands.push(parser.parseOperand());
  8424. if (buildableType) {
  8425. entry.types.push(buildableType);
  8426. }
  8427. } else if (buildableType && (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus))) {
  8428. // Handle integer literals for buildable integer types (e.g., I32)
  8429. let value = '';
  8430. if (parser.consumeIf(_.Token.minus)) {
  8431. value = '-';
  8432. }
  8433. value += parser.getToken().getSpelling().str();
  8434. parser.consumeToken(_.Token.integer);
  8435. entry.operands.push({ name: value, literal: true });
  8436. entry.types.push(buildableType);
  8437. } else if (parser.getToken().is(_.Token.l_brace)) {
  8438. // Check if this is a region, not an operand
  8439. const isActualOperand = opInfo.metadata?.operands?.some((inp) => inp.name === name);
  8440. if (!isActualOperand) {
  8441. const regionMeta = opInfo.metadata?.regions?.find((r) => r.name === name);
  8442. const isVariadicRegion = regionMeta?.type?.name === 'VariadicRegion';
  8443. const isIsolated = op.name.hasTrait('IsolatedFromAbove');
  8444. if (isVariadicRegion) {
  8445. do {
  8446. parser.parseRegion(op.addRegion(), undefined, isIsolated);
  8447. } while (parser.parseOptionalComma() && parser.getToken().is(_.Token.l_brace));
  8448. } else {
  8449. parser.parseRegion(op.addRegion(), undefined, isIsolated);
  8450. }
  8451. }
  8452. } else if (parser.getToken().is(_.Token.at_identifier)) {
  8453. const attrVal = parser.getToken().getSpelling().str();
  8454. parser.consumeToken(_.Token.at_identifier);
  8455. op.addAttribute(name, attrVal);
  8456. } else if (!isOptionalOp && parser.getToken().is(_.Token.bare_identifier)) {
  8457. // Check if this is an enum type that should be an attribute
  8458. // Enum types have a values array after type parsing
  8459. const inputType = input?.type;
  8460. if (inputType && Array.isArray(inputType.values)) {
  8461. const attrVal = parser.getToken().getSpelling().str();
  8462. parser.consumeToken(_.Token.bare_identifier);
  8463. op.addAttribute(name, attrVal);
  8464. } else {
  8465. throw new mlir.Error(`Variable '${name}' has incorrect metadata (expected attribute, got operand).`);
  8466. }
  8467. } else if (!isOptionalOp && parser.getToken().is(_.Token.integer)) {
  8468. const attrVal = parser.getToken().getSpelling().str();
  8469. parser.consumeToken(_.Token.integer);
  8470. op.addAttribute(name, attrVal);
  8471. } else if (!isOptionalOp && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.r_square) && parser.getToken().isNot(_.Token.r_brace) && parser.getToken().isNot(_.Token.eof)) {
  8472. const attr = parser.parseAttribute();
  8473. if (attr) {
  8474. op.addAttribute(name, attr);
  8475. }
  8476. }
  8477. break;
  8478. }
  8479. case 'operands': {
  8480. if (!vars.has('operands')) {
  8481. vars.set('operands', { operands: [], types: [] });
  8482. }
  8483. const operandsList = parser.parseOperandList();
  8484. vars.get('operands').operands.push(...operandsList);
  8485. break;
  8486. }
  8487. case 'results': {
  8488. const args = parser.parseArgumentList('none', true);
  8489. const types = args.map((a) => a.type).filter((t) => t);
  8490. op.addTypes(types);
  8491. break;
  8492. }
  8493. case 'type':
  8494. case 'qualified': {
  8495. if (!directive.args || directive.args.length === 0) {
  8496. // Bare type directive - parse types for operands
  8497. const types = parser.parseTypeListNoParens();
  8498. if (vars.has('operands')) {
  8499. vars.get('operands').types.push(...types);
  8500. }
  8501. break;
  8502. }
  8503. const arg = directive.args[0] === 'type' && directive.args.length > 1 ? directive.args[1] : directive.args[0];
  8504. // Handle qualified($attr) - attribute reference
  8505. if (directive.type === 'qualified' && arg.startsWith('$') && !arg.startsWith('$results') && !arg.startsWith('$operands')) {
  8506. if (!arg.startsWith('type($')) {
  8507. const attrName = arg.substring(1);
  8508. const attr = parser.parseAttribute();
  8509. if (attr) {
  8510. // Store full attribute object to preserve .type for FirstAttrDerivedResultType
  8511. op.addAttribute(attrName, attr);
  8512. }
  8513. break;
  8514. }
  8515. }
  8516. // Extract name from $name or type($name) or type(operands) or type(results)
  8517. let name = null;
  8518. if (arg.startsWith('type($') && arg.endsWith(')')) {
  8519. name = arg.substring(6, arg.length - 1);
  8520. } else if (arg.startsWith('type(') && arg.endsWith(')')) {
  8521. // Handle type(operands) or type(results)
  8522. name = arg.substring(5, arg.length - 1);
  8523. } else if (arg.startsWith('$')) {
  8524. name = arg.substring(1);
  8525. } else if (arg === 'results' || arg === 'operands') {
  8526. name = arg;
  8527. }
  8528. if (!name) {
  8529. break;
  8530. }
  8531. // Check if it's a result or operand
  8532. const resultMeta = opInfo.metadata?.results?.find((r) => r.name === name);
  8533. const operandMeta = opInfo.metadata?.operands?.find((o) => o.name === name);
  8534. const isResult = Boolean(resultMeta) && !operandMeta;
  8535. let isVariadicType = false;
  8536. if (resultMeta) {
  8537. isVariadicType = isVariadic(resultMeta.type);
  8538. } else if (operandMeta) {
  8539. isVariadicType = isVariadic(operandMeta.type);
  8540. }
  8541. const isVariadicOfVariadicType = operandMeta ? isVariadicOfVariadic(operandMeta.type) : false;
  8542. let isOptionalType = false;
  8543. if (operandMeta) {
  8544. isOptionalType = isOptional(operandMeta.type);
  8545. } else if (resultMeta) {
  8546. isOptionalType = isOptional(resultMeta.type);
  8547. }
  8548. if (!vars.has(name)) {
  8549. vars.set(name, { operands: [], types: [] });
  8550. }
  8551. const entry = vars.get(name);
  8552. if (isResult || name === 'results') {
  8553. // Result type - add to op.types and track in entry.types
  8554. if (isVariadicType || name === 'results') {
  8555. const types = parser.parseTypeListNoParens();
  8556. entry.types.push(...types);
  8557. op.addTypes(types);
  8558. } else if (isOptionalType && op.types.length === 0) {
  8559. const type = parser.parseOptionalType();
  8560. if (type) {
  8561. entry.types.push(type);
  8562. op.addTypes([type]);
  8563. }
  8564. } else {
  8565. const type = this.parseCustomTypeWithFallback(parser, resultMeta?.type);
  8566. entry.types.push(type);
  8567. op.addTypes([type]);
  8568. }
  8569. } else if (isVariadicOfVariadicType) {
  8570. // Parse grouped types: (type, type), (), (type)
  8571. do {
  8572. if (!parser.parseOptionalLParen()) {
  8573. break;
  8574. }
  8575. if (parser.getToken().isNot(_.Token.r_paren)) {
  8576. entry.types.push(...parser.parseTypeListNoParens());
  8577. }
  8578. parser.parseRParen();
  8579. } while (parser.parseOptionalComma());
  8580. } else if (isVariadicType || name === 'operands') {
  8581. // Variadic operand - parse type list
  8582. entry.types.push(...parser.parseTypeListNoParens());
  8583. } else if (entry.operands.length > 0) {
  8584. // Single operand - parse one type per operand
  8585. // Clear any previously inferred (buildable) types since explicit type is parsed
  8586. const type = this.parseCustomTypeWithFallback(parser, operandMeta?.type);
  8587. entry.types = [];
  8588. for (let j = 0; j < entry.operands.length; j++) {
  8589. entry.types.push(type);
  8590. }
  8591. } else if (isOptionalType) {
  8592. // Optional operand - parse type if present
  8593. const type = parser.parseOptionalType();
  8594. if (type) {
  8595. entry.types.push(type);
  8596. }
  8597. } else {
  8598. // No operands collected yet, just parse and store type
  8599. // Use custom type parser if available for the operand/result constraint
  8600. const typeConstraint = operandMeta?.type || resultMeta?.type;
  8601. const type = this.parseCustomTypeWithFallback(parser, typeConstraint);
  8602. entry.types.push(type);
  8603. }
  8604. break;
  8605. }
  8606. case 'attr_dict_with_keyword':
  8607. if (parser.parseOptionalKeyword('attributes')) {
  8608. parser.parseAttributeDict(op.attributes);
  8609. }
  8610. break;
  8611. case 'attr_dict':
  8612. if (parser.getToken().is(_.Token.l_brace)) {
  8613. parser.parseAttributeDict(op.attributes);
  8614. }
  8615. break;
  8616. case 'prop_dict':
  8617. if (parser.parseOptionalLess()) {
  8618. op.propertiesAttr = parser.parseAttribute();
  8619. parser.parseGreater();
  8620. }
  8621. break;
  8622. case 'regions': {
  8623. const isIsolated = op.name.hasTrait('IsolatedFromAbove');
  8624. while (parser.getToken().is(_.Token.l_brace)) {
  8625. const region = op.addRegion();
  8626. parser.parseRegion(region, undefined, isIsolated);
  8627. if (!parser.parseOptionalComma()) {
  8628. break;
  8629. }
  8630. }
  8631. break;
  8632. }
  8633. case 'successors': {
  8634. op.successors = op.successors || [];
  8635. if (parser.getToken().is(_.Token.caret_identifier)) {
  8636. op.successors.push({ label: parser.getToken().getSpelling().str() });
  8637. parser.consumeToken(_.Token.caret_identifier);
  8638. while (parser.parseOptionalComma()) {
  8639. if (parser.getToken().is(_.Token.caret_identifier)) {
  8640. op.successors.push({ label: parser.getToken().getSpelling().str() });
  8641. parser.consumeToken(_.Token.caret_identifier);
  8642. } else {
  8643. break;
  8644. }
  8645. }
  8646. }
  8647. break;
  8648. }
  8649. case 'functional_type': {
  8650. const type = parser.parseFunctionType();
  8651. if (!(type instanceof _.FunctionType)) {
  8652. throw new mlir.Error('Invalid functional-type function type.');
  8653. }
  8654. // Distribute input types to operands in metadata order
  8655. let typeIndex = 0;
  8656. for (const operandMeta of opInfo.metadata?.operands || []) {
  8657. if (vars.has(operandMeta.name)) {
  8658. const entry = vars.get(operandMeta.name);
  8659. for (let j = 0; j < entry.operands.length && typeIndex < type.inputs.length; j++) {
  8660. entry.types.push(type.inputs[typeIndex]);
  8661. typeIndex++;
  8662. }
  8663. }
  8664. }
  8665. op.addTypes(type.results);
  8666. // Track result types - second arg is typically the result (e.g., $outputs or results)
  8667. if (directive.args && directive.args.length > 1) {
  8668. const resultArg = directive.args[1];
  8669. if (resultArg) {
  8670. // Handle both $name and name (without $)
  8671. const resultName = resultArg.startsWith('$') ? resultArg.substring(1) : resultArg;
  8672. if (resultName === 'results') {
  8673. // 'results' is a keyword meaning all results - create vars entry
  8674. if (!vars.has('results')) {
  8675. vars.set('results', { types: [] });
  8676. }
  8677. vars.get('results').types.push(...type.results);
  8678. } else if (vars.has(resultName)) {
  8679. vars.get(resultName).types.push(...type.results);
  8680. }
  8681. }
  8682. }
  8683. break;
  8684. }
  8685. case 'custom': {
  8686. const fn = this._customDirectives.get(directive.parser);
  8687. if (!fn) {
  8688. throw new mlir.Error(`Custom directive parser '${directive.parser}' not implemented.`);
  8689. }
  8690. // Parse args and pass resolved arrays
  8691. // Always pass parser and op first, then resolved args
  8692. const callArgs = [parser, op];
  8693. for (const arg of directive.args || []) {
  8694. if (arg.startsWith('ref(type($') && arg.endsWith('))')) {
  8695. // ref(type($name)) - reference to the type of an operand
  8696. // 'ref(type($' is 10 characters, so slice from index 10 to skip -2 for '))'
  8697. const name = arg.slice(10, -2);
  8698. if (!vars.has(name)) {
  8699. vars.set(name, { operands: [], types: [] });
  8700. }
  8701. callArgs.push(vars.get(name).types);
  8702. } else if (arg.startsWith('ref($') && arg.endsWith(')')) {
  8703. const name = arg.slice(5, -1);
  8704. // Check if this is an attribute reference
  8705. const isAttribute = opInfo.metadata?.attributes?.some((a) => a.name === name);
  8706. if (isAttribute) {
  8707. // Get attribute value from op.attributes
  8708. const attrValue = op.attributes.get(name);
  8709. callArgs.push(attrValue);
  8710. } else {
  8711. // Operand reference - get from ctx
  8712. if (!vars.has(name)) {
  8713. vars.set(name, { operands: [], types: [] });
  8714. }
  8715. callArgs.push(vars.get(name).operands);
  8716. }
  8717. } else if (arg.startsWith('type($') && arg.endsWith(')')) {
  8718. const name = arg.slice(6, -1);
  8719. // Always use vars entry for the specific name (result or operand)
  8720. // This ensures Optional results like asyncToken are tracked separately
  8721. if (!vars.has(name)) {
  8722. vars.set(name, { operands: [], types: [] });
  8723. }
  8724. callArgs.push(vars.get(name).types);
  8725. } else if (arg.startsWith('$')) {
  8726. const name = arg.slice(1);
  8727. // Could be operand ref or attribute name
  8728. const isOperand = opInfo.metadata?.operands?.some((o) => o.name === name);
  8729. if (isOperand) {
  8730. if (!vars.has(name)) {
  8731. vars.set(name, { operands: [], types: [] });
  8732. }
  8733. callArgs.push(vars.get(name).operands);
  8734. } else {
  8735. // Pass attribute name for custom directive to handle
  8736. callArgs.push(name);
  8737. }
  8738. } else {
  8739. // Warn if a $-prefixed arg wasn't resolved - indicates missing metadata
  8740. if (typeof arg === 'string' && arg.startsWith('$')) {
  8741. throw new mlir.Error(`Custom directive '${directive.parser}' received unresolved arg '${arg}' for op '${opInfo.metadata.name}'. Check metadata for missing operand/attribute definition.`);
  8742. }
  8743. callArgs.push(arg);
  8744. }
  8745. }
  8746. fn(...callArgs);
  8747. break;
  8748. }
  8749. case 'oilist': {
  8750. const clauses = directive.content.split('|').map((c) => c.trim());
  8751. const parsedClauses = [];
  8752. for (const clauseStr of clauses) {
  8753. const clauseParser = new _.AssemblyFormatParser({ ...opInfo.metadata, assemblyFormat: clauseStr });
  8754. const elements = clauseParser.parse();
  8755. parsedClauses.push({ elements, parsed: false, clauseStr });
  8756. }
  8757. // Helper to check if a clause's variables are used by later custom directives
  8758. const isHandledByCustomDirective = (clauseStr) => {
  8759. const varMatches = clauseStr.matchAll(/\$(\w+)/g);
  8760. const clauseVars = [...varMatches].map((m) => m[1]);
  8761. if (clauseVars.length === 0) {
  8762. return false;
  8763. }
  8764. for (let j = i + 1; j < directives.length; j++) {
  8765. const laterDir = directives[j];
  8766. if (laterDir.type === 'custom' && laterDir.args && Array.isArray(laterDir.args)) {
  8767. const customVarNames = [];
  8768. for (const arg of laterDir.args) {
  8769. const argVarMatches = arg.matchAll(/\$(\w+)/g);
  8770. for (const match of argVarMatches) {
  8771. customVarNames.push(match[1]);
  8772. }
  8773. }
  8774. if (clauseVars.some((v) => customVarNames.includes(v))) {
  8775. return true;
  8776. }
  8777. }
  8778. }
  8779. return false;
  8780. };
  8781. let progress = true;
  8782. while (progress) {
  8783. progress = false;
  8784. for (const clause of parsedClauses) {
  8785. if (clause.parsed) {
  8786. continue;
  8787. }
  8788. if (clause.elements.length === 0) {
  8789. continue;
  8790. }
  8791. if (isHandledByCustomDirective(clause.clauseStr)) {
  8792. clause.parsed = true;
  8793. continue;
  8794. }
  8795. const [firstElem] = clause.elements;
  8796. let matches = false;
  8797. if (firstElem.type === 'literal') {
  8798. if (firstElem.value.length === 1 && /[(){}[\],:<>=]/.test(firstElem.value)) {
  8799. matches = parser.getToken().is(firstElem.value);
  8800. } else {
  8801. matches = parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === firstElem.value || parser.getToken().is(`kw_${firstElem.value}`);
  8802. }
  8803. }
  8804. if (matches) {
  8805. for (const elem of clause.elements) {
  8806. this.parseDirective(elem, parser, op, opInfo, directives, i, vars);
  8807. }
  8808. clause.parsed = true;
  8809. progress = true;
  8810. }
  8811. }
  8812. }
  8813. break;
  8814. }
  8815. case 'optional_group': {
  8816. let shouldParse = false;
  8817. const firstElem = directive.elements.find((elem) => elem.type !== 'whitespace');
  8818. if (firstElem) {
  8819. if (firstElem.type === 'literal') {
  8820. if (firstElem.value.length === 1 && /[(){}[\],:<>=?]/.test(firstElem.value)) {
  8821. shouldParse = parser.getToken().is(firstElem.value);
  8822. } else if (firstElem.value === '->') {
  8823. shouldParse = parser.getToken().is(_.Token.arrow);
  8824. } else if (firstElem.value === '...') {
  8825. shouldParse = parser.getToken().is(_.Token.ellipsis);
  8826. } else {
  8827. shouldParse = parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === firstElem.value || parser.getToken().is(`kw_${firstElem.value}`);
  8828. }
  8829. } else if (firstElem.type === 'attribute_ref') {
  8830. const attrInfo = opInfo.metadata && opInfo.metadata.attributes && opInfo.metadata.attributes.find((attr) => attr.name === firstElem.name);
  8831. const attrType = attrInfo ? attrInfo.type : null;
  8832. // Check if attribute type is an array (TypedArrayAttrBase, ArrayAttr, etc.)
  8833. // Handle both string types ("OptionalAttr<StrAttr>") and object types ({name: "OptionalAttr", args: [...]})
  8834. let elementType = attrType;
  8835. const getTypeName = (t) => typeof t === 'string' ? t : t?.name;
  8836. const typeContains = (t, pattern) => {
  8837. const name = typeof t === 'string' ? t : t?.name;
  8838. return name && name.includes(pattern);
  8839. };
  8840. // Unwrap wrapper types
  8841. if (typeContains(elementType, 'OptionalAttr')) {
  8842. elementType = typeof elementType === 'string' ? elementType.replace(/OptionalAttr<(.+)>/, '$1') : elementType.args?.[0];
  8843. }
  8844. if (typeContains(elementType, 'DefaultValuedAttr') || typeContains(elementType, 'DefaultValuedStrAttr')) {
  8845. elementType = typeof elementType === 'string' ? elementType.replace(/DefaultValuedAttr<(.+?)(?:,.*?)?>/, '$1') : elementType.args?.[0];
  8846. }
  8847. if (typeContains(elementType, 'ConfinedAttr')) {
  8848. elementType = typeof elementType === 'string' ? elementType.replace(/ConfinedAttr<(.+?)(?:,.*?)?>/, '$1') : elementType.args?.[0];
  8849. }
  8850. const typeName = getTypeName(elementType);
  8851. let shouldTryParse = false;
  8852. if (typeContains(elementType, 'TypedArrayAttrBase') || typeContains(elementType, 'ArrayAttr')) {
  8853. shouldTryParse = parser.getToken().is(_.Token.l_square);
  8854. } else if (typeName && /^[SU]?I\d+Attr$|^IntegerAttr$|^IndexAttr$/.test(typeName)) {
  8855. shouldTryParse = parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus);
  8856. } else if (typeContains(elementType, 'ElementsAttr')) {
  8857. // ElementsAttr values start with specific keywords: dense, sparse, array, dense_resource
  8858. shouldTryParse = parser.getToken().is(_.Token.kw_dense) || parser.getToken().is(_.Token.kw_sparse) ||
  8859. parser.getToken().is(_.Token.kw_array) || parser.getToken().is(_.Token.kw_dense_resource);
  8860. } else if (typeName === 'StrAttr' || typeName === 'StringAttr') {
  8861. shouldTryParse = parser.getToken().is(_.Token.string);
  8862. } else {
  8863. shouldTryParse = parser.getToken().is(_.Token.bare_identifier) || parser.getToken().isKeyword() || parser.getToken().is(_.Token.hash_identifier) || parser.getToken().is(_.Token.at_identifier) || parser.getToken().is(_.Token.string) || parser.getToken().is(_.Token.l_square) || parser.getToken().is(_.Token.integer);
  8864. }
  8865. if (shouldTryParse) {
  8866. let result = null;
  8867. if (attrType && attrType !== 'Attribute') {
  8868. result = this.parseCustomAttributeWithFallback(parser, attrType);
  8869. } else {
  8870. result = parser.parseOptionalAttribute(attrType || 'Attribute');
  8871. }
  8872. if (result !== null) {
  8873. op.addAttribute(firstElem.name, result);
  8874. shouldParse = true;
  8875. }
  8876. }
  8877. } else if (firstElem.type === 'successor_ref') {
  8878. shouldParse = parser.getToken().is(_.Token.caret_identifier);
  8879. } else if (firstElem.type === 'region_ref') {
  8880. shouldParse = parser.getToken().is(_.Token.l_brace);
  8881. } else if (firstElem.type === 'operand_ref') {
  8882. let isKeywordInput = false;
  8883. if (opInfo.metadata && opInfo.metadata.operands) {
  8884. const inputInfo = opInfo.metadata.operands.find((inp) => inp.name === firstElem.name);
  8885. if (inputInfo) {
  8886. const inputType = inputInfo.type;
  8887. if (typeof inputType === 'string' &&
  8888. (inputType.includes('Prop') || inputType.endsWith('Predicate') ||
  8889. inputType.includes('Flags') || inputType.includes('Enum'))) {
  8890. isKeywordInput = true;
  8891. }
  8892. }
  8893. }
  8894. if (isKeywordInput) {
  8895. shouldParse = parser.getToken().is(_.Token.bare_identifier);
  8896. } else {
  8897. shouldParse = parser.getToken().is(_.Token.percent_identifier);
  8898. }
  8899. } else if (firstElem.type === 'operands') {
  8900. shouldParse = parser.getToken().is(_.Token.l_paren) || parser.getToken().is(_.Token.percent_identifier);
  8901. } else if (firstElem.type === 'custom') {
  8902. const fn = this._customDirectives.get(firstElem.parser);
  8903. if (fn) {
  8904. const resolvedArgs = (firstElem.args || []).map((arg) => typeof arg === 'string' && arg.startsWith('$') ? arg.slice(1) : arg);
  8905. const result = fn(parser, op, ...resolvedArgs);
  8906. if (result === null) {
  8907. shouldParse = false;
  8908. } else {
  8909. shouldParse = 'skip_first';
  8910. }
  8911. }
  8912. } else if (firstElem.type === 'qualified') {
  8913. if (firstElem.args && firstElem.args.length > 0) {
  8914. const [arg] = firstElem.args;
  8915. if (arg.startsWith('$')) {
  8916. shouldParse = parser.getToken().is(_.Token.hash_identifier);
  8917. } else if (arg.startsWith('type($')) {
  8918. shouldParse = parser.getToken().is(_.Token.exclamation_identifier) || parser.getToken().is(_.Token.bare_identifier);
  8919. }
  8920. }
  8921. }
  8922. }
  8923. if (shouldParse) {
  8924. // Recursively parse nested elements using the same parseDirective method
  8925. // If shouldParse === 'skip_first', the custom directive already parsed the first element
  8926. const startIdx = shouldParse === 'skip_first' ? 1 : 0;
  8927. for (let elemIdx = startIdx; elemIdx < directive.elements.length; elemIdx++) {
  8928. this.parseDirective(directive.elements[elemIdx], parser, op, opInfo, directive.elements, elemIdx, vars);
  8929. }
  8930. }
  8931. break;
  8932. }
  8933. case 'conditional_alternative': {
  8934. const checkMatch = (elem) => {
  8935. if (elem.type === 'literal') {
  8936. if (elem.value.length === 1 && /[(){}[\],:<>=?]/.test(elem.value)) {
  8937. return parser.getToken().is(elem.value);
  8938. }
  8939. return parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === elem.value || parser.getToken().is(`kw_${elem.value}`);
  8940. }
  8941. if (elem.type === 'operand_ref') {
  8942. return parser.getToken().is(_.Token.percent_identifier);
  8943. }
  8944. if (elem.type === 'attribute_ref') {
  8945. return parser.getToken().is(_.Token.bare_identifier) || parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.floatliteral) || parser.getToken().is(_.Token.l_square) || parser.getToken().is(_.Token.at_identifier) || parser.getToken().is(_.Token.hash_identifier);
  8946. }
  8947. if (elem.type === 'region_ref') {
  8948. return parser.getToken().is(_.Token.l_brace);
  8949. }
  8950. if (elem.type === 'successor_ref') {
  8951. return parser.getToken().is(_.Token.caret_identifier);
  8952. }
  8953. if (elem.type === 'custom') {
  8954. // Custom directives can start with various tokens including negative integers
  8955. return parser.getToken().is(_.Token.bare_identifier) || parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus) || parser.getToken().is(_.Token.percent_identifier) || parser.getToken().is(_.Token.l_square) || parser.getToken().is(_.Token.l_paren) || parser.getToken().is(_.Token.question);
  8956. }
  8957. return false;
  8958. };
  8959. const firstElem = directive.firstAlt.find((e) => e.type !== 'whitespace');
  8960. let matchedFirst = firstElem && checkMatch(firstElem);
  8961. let customDirectiveHandledFirst = false;
  8962. // For custom directives, try calling them and check if they return null
  8963. if (matchedFirst && firstElem.type === 'custom') {
  8964. const fn = this._customDirectives.get(firstElem.parser);
  8965. if (fn) {
  8966. const resolvedArgs = (firstElem.args || []).map((arg) => {
  8967. if (typeof arg === 'string' && arg.startsWith('$')) {
  8968. return arg.slice(1); // Strip $ prefix to get attribute name
  8969. }
  8970. return arg;
  8971. });
  8972. const result = fn(parser, op, ...resolvedArgs);
  8973. if (result === null) {
  8974. matchedFirst = false;
  8975. } else {
  8976. customDirectiveHandledFirst = true;
  8977. }
  8978. }
  8979. }
  8980. if (matchedFirst) {
  8981. const startIdx = customDirectiveHandledFirst ? 1 : 0;
  8982. for (let elemIdx = startIdx; elemIdx < directive.firstAlt.length; elemIdx++) {
  8983. this.parseDirective(directive.firstAlt[elemIdx], parser, op, opInfo, directive.firstAlt, elemIdx, vars);
  8984. }
  8985. } else if (directive.secondOptional) {
  8986. const secondElem = directive.secondAlt.find((e) => e.type !== 'whitespace');
  8987. const matchedSecond = secondElem && checkMatch(secondElem);
  8988. if (matchedSecond) {
  8989. for (const elem of directive.secondAlt) {
  8990. this.parseDirective(elem, parser, op, opInfo, directive.secondAlt, 0, vars);
  8991. }
  8992. }
  8993. } else if (directive.secondAlt && directive.secondAlt.length > 0) {
  8994. for (const elem of directive.secondAlt) {
  8995. this.parseDirective(elem, parser, op, opInfo, directive.secondAlt, 0, vars);
  8996. }
  8997. }
  8998. break;
  8999. }
  9000. default: {
  9001. throw new mlir.Error(`Unsupported directive type '${directive.type}' ${parser.location()}.`);
  9002. }
  9003. }
  9004. }
  9005. parseOperation(parser, result) {
  9006. const opInfo = result.name.getRegisteredInfo();
  9007. if (!opInfo) {
  9008. return false;
  9009. }
  9010. if ((opInfo.metadata.hasParser || opInfo.metadata.hasCustomAssemblyFormat) && !opInfo.metadata.assemblyFormat) {
  9011. throw new mlir.Error(`Operation parser '${result.op}' not implemented.`);
  9012. }
  9013. // Mark as using assembly format parsing (bypasses validation check)
  9014. if (result.compatibility === undefined && opInfo.metadata.assemblyFormat) {
  9015. result.compatibility = true;
  9016. }
  9017. const vars = new Map();
  9018. for (const input of opInfo.metadata?.operands || []) {
  9019. vars.set(input.name, { operands: [], types: [] });
  9020. }
  9021. for (const resultInfo of opInfo.metadata?.results || []) {
  9022. vars.set(resultInfo.name, { types: [] });
  9023. }
  9024. const directives = opInfo.directives || [];
  9025. for (let i = 0; i < directives.length; i++) {
  9026. this.parseDirective(directives[i], parser, result, opInfo, directives, i, vars);
  9027. }
  9028. for (const [, v] of vars) {
  9029. if (v.operands?.length > 0 && v.types?.length > 0) {
  9030. parser.resolveOperands(v.operands, v.types, result.operands);
  9031. } else if (v.operands?.length > 0 && result.types.length > 0) {
  9032. // SameOperandsAndResultType: use result type for operands
  9033. const types = v.operands.map(() => result.types[0]);
  9034. parser.resolveOperands(v.operands, types, result.operands);
  9035. } else if (v.operands?.length > 0) {
  9036. // No explicit type - resolve from scope (type from definition)
  9037. for (const operand of v.operands) {
  9038. parser.resolveOperand(operand, null, result.operands);
  9039. }
  9040. }
  9041. }
  9042. // AttrSizedOperandSegments trait
  9043. if (vars && opInfo.metadata?.operands && result.name.hasTrait('AttrSizedOperandSegments')) {
  9044. const segmentSizes = [];
  9045. for (const operandMeta of opInfo.metadata.operands) {
  9046. const entry = vars.get(operandMeta.name);
  9047. segmentSizes.push(entry?.operands?.length || 0);
  9048. }
  9049. result.addAttribute('operandSegmentSizes', segmentSizes);
  9050. }
  9051. this.inferResultTypes(result, vars);
  9052. return true;
  9053. }
  9054. parseType(parser, dialect) {
  9055. const mnemonic = parser.parseOptionalKeyword();
  9056. if (mnemonic) {
  9057. let type = `!${dialect}.${mnemonic}`;
  9058. if (parser.getToken().is(_.Token.less)) {
  9059. type += parser.skip('<');
  9060. }
  9061. return new _.Type(type);
  9062. }
  9063. return null;
  9064. }
  9065. parseAttribute(/* parser, type */) {
  9066. return null;
  9067. }
  9068. parseCustomTypeWithFallback(parser, type) {
  9069. const optionalType = parser.parseOptionalType();
  9070. if (optionalType) {
  9071. return optionalType;
  9072. }
  9073. if (type && this._customTypes.has(type.name)) {
  9074. let typeT = this._customTypes.get(type.name);
  9075. if (typeof typeT !== 'function') {
  9076. typeT = { type, name: typeT };
  9077. }
  9078. return parser.parseCustomTypeWithFallback(typeT);
  9079. }
  9080. throw new mlir.Error(`Unsupported type constraint '${type}'.`);
  9081. }
  9082. parseCustomAttributeWithFallback(parser, type) {
  9083. if (type && this._customAttributes.has(type.name)) {
  9084. const attrT = this._customAttributes.get(type.name);
  9085. return parser.parseCustomAttributeWithFallback(attrT, type);
  9086. }
  9087. if (type && Array.isArray(type.values)) {
  9088. const value = parser.parseOptionalKeyword(type.values);
  9089. if (value !== null) {
  9090. return new _.TypedAttr(value, null);
  9091. }
  9092. }
  9093. return parser.parseOptionalAttribute(null);
  9094. }
  9095. parseOptionalAttr(parser, type) {
  9096. if (!Array.isArray(type.args) || type.args.length === 0) {
  9097. throw new mlir.Error(`Invalid 'OptionalAttr' type.`);
  9098. }
  9099. const [elementType] = type.args;
  9100. return this.parseCustomAttributeWithFallback(parser, elementType);
  9101. }
  9102. parseDefaultValuedAttr(parser, type) {
  9103. if (!Array.isArray(type.args) || type.args.length === 0) {
  9104. throw new mlir.Error(`Invalid 'DefaultValuedAttr' type.`);
  9105. }
  9106. const [elementType] = type.args;
  9107. return this.parseCustomAttributeWithFallback(parser, elementType);
  9108. }
  9109. parseDefaultValuedOptionalAttr(parser, type) {
  9110. if (!Array.isArray(type.args) || type.args.length === 0) {
  9111. throw new mlir.Error(`Invalid 'DefaultValuedOptionalAttr' type.`);
  9112. }
  9113. const [elementType] = type.args;
  9114. return this.parseCustomAttributeWithFallback(parser, elementType);
  9115. }
  9116. parseTypeAttrOf(parser, type) {
  9117. if (!Array.isArray(type.args) || type.args.length === 0) {
  9118. throw new mlir.Error(`Invalid 'TypeAttrOf' type.`);
  9119. }
  9120. const parsedType = parser.parseOptionalType();
  9121. if (parsedType) {
  9122. return { value: parsedType, type: 'type' };
  9123. }
  9124. return null;
  9125. }
  9126. parseAnyAttrOf(parser) {
  9127. // This allows parseAttribute to handle the full syntax including `: type` suffix
  9128. return parser.parseOptionalAttribute(null);
  9129. }
  9130. parseArrayAttr(parser) {
  9131. if (parser.getToken().is(_.Token.l_square)) {
  9132. return parser.parseOptionalAttribute();
  9133. }
  9134. // Handle attribute alias references that resolve to arrays
  9135. if (parser.getToken().is(_.Token.hash_identifier)) {
  9136. return parser.parseAttribute();
  9137. }
  9138. return null;
  9139. }
  9140. parseConfinedAttr(parser, type) {
  9141. if (!Array.isArray(type.args) || type.args.length === 0) {
  9142. throw new mlir.Error(`Invalid ConfinedAttr type.`);
  9143. }
  9144. const [baseType] = type.args;
  9145. return this.parseCustomAttributeWithFallback(parser, baseType);
  9146. }
  9147. parseTypedAttrInterface(parser) {
  9148. return parser.parseAttribute();
  9149. }
  9150. parseUnitAttr(parser) {
  9151. parser.consumeIf(_.Token.kw_unit);
  9152. return new _.UnitAttr();
  9153. }
  9154. parseSymbolNameAttr(parser) {
  9155. const value = parser.parseOptionalSymbolName();
  9156. if (value) {
  9157. return new _.StringAttr(value);
  9158. }
  9159. return null;
  9160. }
  9161. parseSymbolRefAttr(parser) {
  9162. return parser.parseAttribute();
  9163. }
  9164. parseFlatSymbolRefAttr(parser) {
  9165. return this.parseSymbolRefAttr(parser);
  9166. }
  9167. // custom<DynamicIndexList>($dynamic_operands, $static_attr, $scalable_attr?, "Delimiter::Paren"?)
  9168. parseDynamicIndexList(parser, op, operandsAttr, staticAttrName, scalableAttrName, delimiterSpec) {
  9169. // Determine delimiter from delimiterSpec
  9170. let openDelim = '[';
  9171. let closeDelim = ']';
  9172. if (typeof delimiterSpec === 'string' && delimiterSpec.includes('Paren')) {
  9173. openDelim = '(';
  9174. closeDelim = ')';
  9175. }
  9176. const unresolvedOperands = [];
  9177. const staticValues = [];
  9178. const scalableFlags = [];
  9179. if (parser.consumeIf(openDelim)) {
  9180. while (parser.getToken().isNot(closeDelim)) {
  9181. const isScalable = parser.parseOptionalLSquare();
  9182. if (parser.getToken().is(_.Token.percent_identifier)) {
  9183. unresolvedOperands.push(parser.parseOperand());
  9184. staticValues.push(_.ShapedType.kDynamic);
  9185. if (parser.parseOptionalColon()) {
  9186. parser.parseType();
  9187. }
  9188. } else {
  9189. const intVal = parser.parseOptionalInteger();
  9190. if (intVal === null) {
  9191. break;
  9192. }
  9193. staticValues.push(intVal);
  9194. }
  9195. scalableFlags.push(isScalable);
  9196. if (isScalable) {
  9197. if (!parser.parseOptionalRSquare()) {
  9198. throw new mlir.Error(`Expected ']' for scalable index ${parser.location()}`);
  9199. }
  9200. }
  9201. parser.parseOptionalComma();
  9202. }
  9203. parser.consumeToken(closeDelim);
  9204. }
  9205. const indexType = new _.IndexType();
  9206. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), op.operands);
  9207. if (staticAttrName && staticValues.length > 0) {
  9208. op.addAttribute(staticAttrName, staticValues);
  9209. }
  9210. if (scalableFlags.length > 0 && scalableFlags.some((f) => f)) {
  9211. if (!scalableAttrName) {
  9212. throw new mlir.Error(`Scalable indices found but no scalable attribute name provided ${parser.location()}`);
  9213. }
  9214. op.addAttribute(scalableAttrName, scalableFlags);
  9215. }
  9216. }
  9217. parseOffsets(parser, op, attrName) {
  9218. const values = [];
  9219. while (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus)) {
  9220. if (parser.consumeIf(_.Token.minus)) {
  9221. if (parser.getToken().is(_.Token.integer)) {
  9222. values.push(-parser.parseInteger());
  9223. } else {
  9224. throw new mlir.Error(`Expected integer after '-' in offsets ${parser.location()}`);
  9225. }
  9226. } else {
  9227. values.push(parser.parseInteger());
  9228. }
  9229. if (!parser.parseOptionalComma()) {
  9230. break;
  9231. }
  9232. }
  9233. if (attrName) {
  9234. op.addAttribute(attrName, values);
  9235. }
  9236. }
  9237. parseSymbolVisibility(parser, op) {
  9238. const visibility = parser.parseOptionalKeyword(['public', 'private', 'nested']);
  9239. if (visibility) {
  9240. op.addAttribute('sym_visibility', visibility);
  9241. }
  9242. }
  9243. parseTypeOrAttr(parser, op, typeArg, attrArg) {
  9244. if (parser.parseOptionalEqual()) {
  9245. const attr = parser.parseAttribute();
  9246. if (parser.parseOptionalColon()) {
  9247. const type = parser.parseType();
  9248. op.addAttribute(typeArg, type);
  9249. attr.type = type;
  9250. } else if (attr && attr.type) {
  9251. op.addAttribute(typeArg, attr.type);
  9252. }
  9253. op.addAttribute(attrArg, attr);
  9254. return;
  9255. }
  9256. if (parser.parseOptionalColon()) {
  9257. const type = parser.parseType();
  9258. op.addAttribute(typeArg, type);
  9259. if (parser.parseOptionalEqual()) {
  9260. const attr = parser.parseAttribute();
  9261. if (parser.parseOptionalColon()) {
  9262. const attrType = parser.parseType();
  9263. attr.type = attrType;
  9264. }
  9265. op.addAttribute(attrArg, attr);
  9266. }
  9267. return;
  9268. }
  9269. throw new mlir.Error(`Expected ':' or '=' in TypeOrAttr ${parser.location()}`);
  9270. }
  9271. parseSizeAwareType(parser, op, typeArg) {
  9272. const type = parser.parseType();
  9273. parser.parseLBrace();
  9274. const operand = parser.parseOperand();
  9275. parser.parseRBrace();
  9276. if (!Array.isArray(typeArg)) {
  9277. throw new mlir.Error(`Invalid argument 'typeArg'.`);
  9278. }
  9279. if (typeArg.length === 0) {
  9280. typeArg.push(type);
  9281. } else {
  9282. typeArg[0] = type;
  9283. }
  9284. if (operand) {
  9285. parser.resolveOperand(operand, null, op.operands);
  9286. }
  9287. }
  9288. parseCopyOpRegion(parser, result) {
  9289. result.regions.push({ blocks: [] });
  9290. }
  9291. parseResultTypeList(parser, op) {
  9292. parser.parseLParen();
  9293. const types = [];
  9294. if (parser.getToken().isNot(_.Token.r_paren)) {
  9295. do {
  9296. types.push(parser.parseType());
  9297. } while (parser.parseOptionalComma());
  9298. }
  9299. parser.parseRParen();
  9300. if (types.length > 0) {
  9301. op.addAttribute('result_types', types.map((t) => t.toString()));
  9302. }
  9303. }
  9304. parseCmdParameterGatherOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, targetOps, targetTypes, targetSizeOps, targetOffsetsOps, targetLengthsOps) {
  9305. do {
  9306. const firstOperand = parser.parseOperand();
  9307. let key = firstOperand;
  9308. if (parser.parseOptionalColon()) {
  9309. sourceScopeOps.push(firstOperand);
  9310. parser.parseColon();
  9311. key = parser.parseOperand();
  9312. }
  9313. sourceKeysOps.push(key);
  9314. parser.parseLSquare();
  9315. sourceOffsetsOps.push(parser.parseOperand());
  9316. parser.parseRSquare();
  9317. parser.parseArrow();
  9318. const rowTarget = parser.parseOperand();
  9319. if (targetOps.length === 0) {
  9320. targetOps.push(rowTarget);
  9321. }
  9322. parser.parseLSquare();
  9323. targetOffsetsOps.push(parser.parseOperand());
  9324. parser.parseKeyword('for');
  9325. targetLengthsOps.push(parser.parseOperand());
  9326. parser.parseRSquare();
  9327. parser.parseColon();
  9328. const rowType = parser.parseType();
  9329. if (targetTypes.length === 0) {
  9330. targetTypes.push(rowType);
  9331. }
  9332. parser.parseLBrace();
  9333. const rowSize = parser.parseOperand();
  9334. if (targetSizeOps.length === 0) {
  9335. targetSizeOps.push(rowSize);
  9336. }
  9337. parser.parseRBrace();
  9338. } while (parser.parseOptionalComma());
  9339. }
  9340. // custom<AsyncParameterGatherOperations>(...)
  9341. // Parses: %scope::%key[%offset] -> %target[%offset to %end for %length] : type{%size}, ...
  9342. parseAsyncParameterGatherOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, targetOps, targetTypes, targetSizeOps, targetOffsetsOps, targetEndsOps, targetLengthsOps) {
  9343. do {
  9344. const firstOperand = parser.parseOperand();
  9345. let key = firstOperand;
  9346. if (parser.parseOptionalColon()) {
  9347. sourceScopeOps.push(firstOperand);
  9348. parser.parseColon();
  9349. key = parser.parseOperand();
  9350. }
  9351. sourceKeysOps.push(key);
  9352. parser.parseLSquare();
  9353. sourceOffsetsOps.push(parser.parseOperand());
  9354. parser.parseRSquare();
  9355. parser.parseArrow();
  9356. const rowTarget = parser.parseOperand();
  9357. if (targetOps.length === 0) {
  9358. targetOps.push(rowTarget);
  9359. }
  9360. parser.parseLSquare();
  9361. targetOffsetsOps.push(parser.parseOperand());
  9362. parser.parseKeyword('to');
  9363. targetEndsOps.push(parser.parseOperand());
  9364. parser.parseKeyword('for');
  9365. targetLengthsOps.push(parser.parseOperand());
  9366. parser.parseRSquare();
  9367. parser.parseColon();
  9368. const rowType = parser.parseType();
  9369. if (targetTypes.length === 0) {
  9370. targetTypes.push(rowType);
  9371. }
  9372. parser.parseLBrace();
  9373. const rowSize = parser.parseOperand();
  9374. if (targetSizeOps.length === 0) {
  9375. targetSizeOps.push(rowSize);
  9376. }
  9377. parser.parseRBrace();
  9378. } while (parser.parseOptionalComma());
  9379. }
  9380. // custom<CmdParameterScatterOperations>(...)
  9381. // Parses: %source[%offset for %length] : type{%size} -> %scope::%key[%offset], ...
  9382. parseCmdParameterScatterOperations(parser, op, sourceOps, sourceTypes, sourceSizeOps, sourceOffsetsOps, sourceLengthsOps, targetScopeOps, targetKeysOps, targetOffsetsOps) {
  9383. do {
  9384. const rowSource = parser.parseOperand();
  9385. if (sourceOps.length === 0) {
  9386. sourceOps.push(rowSource);
  9387. }
  9388. parser.parseLSquare();
  9389. sourceOffsetsOps.push(parser.parseOperand());
  9390. parser.parseKeyword('for');
  9391. sourceLengthsOps.push(parser.parseOperand());
  9392. parser.parseRSquare();
  9393. parser.parseColon();
  9394. const rowType = parser.parseType();
  9395. if (sourceTypes.length === 0) {
  9396. sourceTypes.push(rowType);
  9397. }
  9398. parser.parseLBrace();
  9399. const rowSize = parser.parseOperand();
  9400. if (sourceSizeOps.length === 0) {
  9401. sourceSizeOps.push(rowSize);
  9402. }
  9403. parser.parseRBrace();
  9404. // Parse -> %scope::%key[%offset]
  9405. parser.parseArrow();
  9406. const firstOperand = parser.parseOperand();
  9407. let key = firstOperand;
  9408. if (parser.parseOptionalColon()) {
  9409. targetScopeOps.push(firstOperand);
  9410. parser.parseColon();
  9411. key = parser.parseOperand();
  9412. }
  9413. targetKeysOps.push(key);
  9414. parser.parseLSquare();
  9415. targetOffsetsOps.push(parser.parseOperand());
  9416. parser.parseRSquare();
  9417. } while (parser.parseOptionalComma());
  9418. }
  9419. // custom<AsyncParameterScatterOperations>(...)
  9420. // Parses: %source[%offset to %end for %length] : type{%size} -> %scope::%key[%offset], ...
  9421. parseAsyncParameterScatterOperations(parser, op, sourceOps, sourceTypes, sourceSizeOps, sourceOffsetsOps, sourceEndsOps, sourceLengthsOps, targetScopeOps, targetKeysOps, targetOffsetsOps) {
  9422. do {
  9423. const rowSource = parser.parseOperand();
  9424. if (sourceOps.length === 0) {
  9425. sourceOps.push(rowSource);
  9426. }
  9427. parser.parseLSquare();
  9428. sourceOffsetsOps.push(parser.parseOperand());
  9429. parser.parseKeyword('to');
  9430. sourceEndsOps.push(parser.parseOperand());
  9431. parser.parseKeyword('for');
  9432. sourceLengthsOps.push(parser.parseOperand());
  9433. parser.parseRSquare();
  9434. parser.parseColon();
  9435. const rowType = parser.parseType();
  9436. if (sourceTypes.length === 0) {
  9437. sourceTypes.push(rowType);
  9438. }
  9439. parser.parseLBrace();
  9440. const rowSize = parser.parseOperand();
  9441. if (sourceSizeOps.length === 0) {
  9442. sourceSizeOps.push(rowSize);
  9443. }
  9444. parser.parseRBrace();
  9445. // Parse -> %scope::%key[%offset]
  9446. parser.parseArrow();
  9447. const firstOperand = parser.parseOperand();
  9448. let key = firstOperand;
  9449. if (parser.parseOptionalColon()) {
  9450. targetScopeOps.push(firstOperand);
  9451. parser.parseColon();
  9452. key = parser.parseOperand();
  9453. }
  9454. targetKeysOps.push(key);
  9455. parser.parseLSquare();
  9456. targetOffsetsOps.push(parser.parseOperand());
  9457. parser.parseRSquare();
  9458. } while (parser.parseOptionalComma());
  9459. }
  9460. parseEnumFlags(parser, type, separator) {
  9461. const flags = [];
  9462. do {
  9463. const value = parser.getToken().getSpelling().str();
  9464. parser.consumeToken(_.Token.bare_identifier);
  9465. if (!type.values.includes(value)) {
  9466. throw new mlir.Error(`Invalid enum value '${value}' ${parser.location()}`);
  9467. }
  9468. flags.push(value);
  9469. } while (parser.consumeIf(separator));
  9470. return new _.TypedAttr(flags.join(', '));
  9471. }
  9472. parseEnumFlagsAngleBracketComma(parser, type) {
  9473. if (parser.parseOptionalLess()) {
  9474. const value = this.parseEnumFlags(parser, type, ',');
  9475. parser.parseGreater();
  9476. return value;
  9477. }
  9478. return parser.parseOptionalAttribute();
  9479. }
  9480. parseEnumFlagsAngleBracketPipe(parser, type) {
  9481. if (parser.parseOptionalLess()) {
  9482. const value = this.parseEnumFlags(parser, type, '|');
  9483. parser.parseGreater();
  9484. return value;
  9485. }
  9486. return parser.parseOptionalAttribute();
  9487. }
  9488. parseOptional(parser) {
  9489. return parser.parseOptionalType();
  9490. }
  9491. };
  9492. _.HLODialect = class extends _.Dialect {
  9493. constructor(operations, name) {
  9494. super(operations, name);
  9495. this.registerCustomDirective('SameOperandsAndResultType', this.parseSameOperandsAndResultType.bind(this));
  9496. this.registerCustomDirective('VariadicSameOperandsAndResultType', this.parseVariadicSameOperandsAndResultType.bind(this));
  9497. this.registerCustomDirective('ComplexOpType', this.parseComplexOpType.bind(this));
  9498. this.registerCustomDirective('SelectOpType', this.parseSelectOpType.bind(this));
  9499. this.registerCustomDirective('TupleOpType', this.parseTupleOpType.bind(this));
  9500. this.registerCustomDirective('PairwiseOpType', this.parsePairwiseOpType.bind(this));
  9501. this.registerCustomDirective('ConvolutionDimensions', this.parseConvolutionDimensions.bind(this));
  9502. this.registerCustomDirective('DotDimensionNumbers', this.parseDotDimensionNumbers.bind(this));
  9503. this.registerCustomDirective('PrecisionConfig', this.parsePrecisionConfig.bind(this));
  9504. this.registerCustomDirective('PrecisionConfigAndAlgorithm', this.parsePrecisionConfigAndAlgorithm.bind(this));
  9505. this.registerCustomDirective('WindowAttributes', this.parseWindowAttributes.bind(this));
  9506. this.registerCustomDirective('SliceRanges', this.parseSliceRanges.bind(this));
  9507. this.registerCustomDirective('CustomCallTarget', this.parseCustomCallTarget.bind(this));
  9508. this.registerCustomDirective('VariadicOperandWithAttribute', this.parseVariadicOperandWithAttribute.bind(this));
  9509. }
  9510. assignFromFunctionType(operandArrays, resultArray, fnType) {
  9511. for (let i = 0; i < operandArrays.length && i < fnType.inputs.length; i++) {
  9512. operandArrays[i].push(fnType.inputs[i]);
  9513. }
  9514. if (fnType.results.length === 1) {
  9515. resultArray.push(fnType.results[0]);
  9516. }
  9517. }
  9518. parseSameOperandsAndResultType(parser, op, ...typeArrays) {
  9519. const type = parser.parseType();
  9520. if (type instanceof _.FunctionType) {
  9521. const operandArrays = typeArrays.slice(0, -1);
  9522. const resultArray = typeArrays[typeArrays.length - 1];
  9523. this.assignFromFunctionType(operandArrays, resultArray, type);
  9524. } else {
  9525. for (const arr of typeArrays) {
  9526. arr.push(type);
  9527. }
  9528. }
  9529. }
  9530. // custom<VariadicSameOperandsAndResultType>(ref($inputs), type($inputs), type($result))
  9531. parseVariadicSameOperandsAndResultType(parser, op, operands, operandTypes, resultTypes) {
  9532. const type = parser.parseType();
  9533. // All operands get the same type
  9534. for (let i = 0; i < operands.length; i++) {
  9535. operandTypes.push(type);
  9536. }
  9537. // Result also gets the same type
  9538. resultTypes.push(type);
  9539. }
  9540. // custom<ComplexOpType>(ref($operands), type($operands), type($result))
  9541. parseComplexOpType(parser, op, operands, operandTypes, resultTypes) {
  9542. const type = parser.parseType();
  9543. for (let i = 0; i < operands.length; i++) {
  9544. operandTypes.push(type);
  9545. }
  9546. resultTypes.push(type);
  9547. }
  9548. // custom<SelectOpType>(type($pred), type($on_true), type($on_false), type($result))
  9549. parseSelectOpType(parser, op, predTypes, onTrueTypes, onFalseTypes, resultTypes) {
  9550. const firstType = parser.parseType();
  9551. if (parser.parseOptionalComma()) {
  9552. const secondType = parser.parseType();
  9553. predTypes.push(firstType);
  9554. onTrueTypes.push(secondType);
  9555. onFalseTypes.push(secondType);
  9556. resultTypes.push(secondType);
  9557. } else {
  9558. predTypes.push(firstType);
  9559. onTrueTypes.push(firstType);
  9560. onFalseTypes.push(firstType);
  9561. resultTypes.push(firstType);
  9562. }
  9563. }
  9564. // custom<TupleOpType>(type($operands), type($result))
  9565. parseTupleOpType(parser, op, operandTypes, resultTypes) {
  9566. const type = parser.parseType();
  9567. operandTypes.push(type);
  9568. resultTypes.push(type);
  9569. }
  9570. // custom<PairwiseOpType>(type($operands), type($results))
  9571. parsePairwiseOpType(parser, op, operandTypes, resultTypes) {
  9572. while (true) {
  9573. const type = parser.parseType();
  9574. if (!type) {
  9575. break;
  9576. }
  9577. operandTypes.push(type);
  9578. resultTypes.push(type);
  9579. if (!parser.parseOptionalComma()) {
  9580. break;
  9581. }
  9582. }
  9583. }
  9584. parseDims(parser) {
  9585. const dims = [];
  9586. if (parser.parseOptionalLSquare()) {
  9587. while (parser.getToken().isNot(_.Token.r_square)) {
  9588. if (parser.getToken().is(_.Token.integer)) {
  9589. dims.push(parseInt(parser.getToken().getSpelling().str(), 10));
  9590. parser.consumeToken();
  9591. } else if (parser.getToken().is(_.Token.bare_identifier)) {
  9592. dims.push(parser.getToken().getSpelling().str());
  9593. parser.consumeToken(_.Token.bare_identifier);
  9594. } else {
  9595. break;
  9596. }
  9597. parser.parseOptionalComma();
  9598. }
  9599. parser.parseOptionalRSquare();
  9600. }
  9601. return dims;
  9602. }
  9603. parseConvolutionDimensions(parser, op, attrName) {
  9604. const input = this.parseDims(parser);
  9605. parser.parseKeyword('x');
  9606. const kernel = this.parseDims(parser);
  9607. parser.parseArrow();
  9608. const output = this.parseDims(parser);
  9609. op.addAttribute(attrName, new _.ConvDimensionNumbersAttr(input, kernel, output));
  9610. }
  9611. parseWindowAttributes(parser, op, stridesAttr, paddingAttr, lhsDilationAttr, rhsDilationAttr, reversalAttr) {
  9612. const windowAttrs = {
  9613. stride: [],
  9614. pad: [],
  9615. lhs_dilate: [],
  9616. rhs_dilate: [],
  9617. window_reversal: []
  9618. };
  9619. const parseArray = () => {
  9620. return parser.parseCommaSeparatedList('square', () => {
  9621. if (parser.getToken().is(_.Token.l_square)) {
  9622. return parseArray();
  9623. }
  9624. const intValue = parser.parseOptionalInteger();
  9625. if (intValue !== null) {
  9626. return intValue;
  9627. }
  9628. if (parser.getToken().is(_.Token.bare_identifier)) {
  9629. const retVal = parser.getToken().getSpelling().str();
  9630. parser.consumeToken(_.Token.bare_identifier);
  9631. return retVal;
  9632. }
  9633. return null;
  9634. });
  9635. };
  9636. while (parser.getToken().isNot(_.Token.r_brace)) {
  9637. if (parser.getToken().is(_.Token.bare_identifier)) {
  9638. const key = parser.getToken().getSpelling().str();
  9639. parser.consumeToken(_.Token.bare_identifier);
  9640. if (parser.parseOptionalEqual()) {
  9641. windowAttrs[key] = parseArray();
  9642. }
  9643. parser.parseOptionalComma();
  9644. } else {
  9645. break;
  9646. }
  9647. }
  9648. if (stridesAttr && windowAttrs.stride.length > 0) {
  9649. op.addAttribute(stridesAttr, windowAttrs.stride);
  9650. }
  9651. if (paddingAttr && windowAttrs.pad.length > 0) {
  9652. op.addAttribute(paddingAttr, windowAttrs.pad);
  9653. }
  9654. if (lhsDilationAttr && windowAttrs.lhs_dilate.length > 0) {
  9655. op.addAttribute(lhsDilationAttr, windowAttrs.lhs_dilate);
  9656. }
  9657. if (rhsDilationAttr && windowAttrs.rhs_dilate.length > 0) {
  9658. op.addAttribute(rhsDilationAttr, windowAttrs.rhs_dilate);
  9659. }
  9660. if (reversalAttr && windowAttrs.window_reversal.length > 0) {
  9661. op.addAttribute(reversalAttr, windowAttrs.window_reversal);
  9662. }
  9663. }
  9664. parseDotDimensionNumbers(parser, op, attrName = 'dot_dimension_numbers') {
  9665. const dimensions = {
  9666. lhs_batching_dimensions: [],
  9667. rhs_batching_dimensions: [],
  9668. lhs_contracting_dimensions: [],
  9669. rhs_contracting_dimensions: []
  9670. };
  9671. const parseIntArray = () => {
  9672. return parser.parseCommaSeparatedList('optionalSquare', () => {
  9673. const value = parser.parseOptionalInteger();
  9674. if (value !== null) {
  9675. return value;
  9676. }
  9677. parser.consumeToken();
  9678. return null;
  9679. });
  9680. };
  9681. const parsePair = () => {
  9682. const first = parseIntArray();
  9683. let second = [];
  9684. if (parser.parseOptionalKeyword('x')) {
  9685. second = parseIntArray();
  9686. }
  9687. return { first, second };
  9688. };
  9689. if (parser.parseOptionalKeyword('batching_dims') || parser.parseOptionalKeyword('batch_dims')) {
  9690. parser.parseEqual();
  9691. const pair = parsePair();
  9692. dimensions.lhs_batching_dimensions = pair.first;
  9693. dimensions.rhs_batching_dimensions = pair.second;
  9694. parser.parseOptionalComma();
  9695. }
  9696. parser.parseKeyword('contracting_dims');
  9697. parser.parseEqual();
  9698. const pair = parsePair();
  9699. dimensions.lhs_contracting_dimensions = pair.first;
  9700. dimensions.rhs_contracting_dimensions = pair.second;
  9701. op.addAttribute(attrName, dimensions);
  9702. }
  9703. parsePrecisionConfig(parser, op /*, args */) {
  9704. parser.parseOptionalComma();
  9705. if (!(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'precision')) {
  9706. return;
  9707. }
  9708. parser.parseKeyword('precision');
  9709. parser.parseEqual();
  9710. const precision = parser.parseCommaSeparatedList('square', () => {
  9711. if (parser.getToken().is(_.Token.bare_identifier)) {
  9712. const retVal = parser.getToken().getSpelling().str();
  9713. parser.consumeToken(_.Token.bare_identifier);
  9714. return retVal;
  9715. }
  9716. parser.consumeToken();
  9717. return null;
  9718. });
  9719. if (precision.length > 0) {
  9720. op.addAttribute('precision_config', precision);
  9721. }
  9722. }
  9723. parsePrecisionConfigAndAlgorithm(parser, op /*, args */) {
  9724. if (!parser.parseOptionalComma()) {
  9725. return;
  9726. }
  9727. if (parser.parseOptionalKeyword('algorithm')) {
  9728. parser.parseOptionalEqual();
  9729. const algorithm = parser.parseAttribute();
  9730. op.addAttribute('algorithm', algorithm);
  9731. return;
  9732. }
  9733. if (parser.parseOptionalKeyword('precision')) {
  9734. parser.parseOptionalEqual();
  9735. const precision = parser.parseCommaSeparatedList('optionalSquare', () => {
  9736. if (parser.getToken().is(_.Token.bare_identifier)) {
  9737. const retVal = parser.getToken().getSpelling().str();
  9738. parser.consumeToken(_.Token.bare_identifier);
  9739. return retVal;
  9740. }
  9741. parser.consumeToken();
  9742. return null;
  9743. });
  9744. if (precision.length > 0) {
  9745. op.addAttribute('precision_config', precision);
  9746. }
  9747. if (parser.parseOptionalComma()) {
  9748. if (parser.parseOptionalKeyword('algorithm')) {
  9749. parser.parseOptionalEqual();
  9750. const algorithm = parser.parseAttribute();
  9751. op.addAttribute('algorithm', algorithm);
  9752. }
  9753. }
  9754. }
  9755. }
  9756. parseSliceRanges(parser, op /*, args */) {
  9757. const ranges = {
  9758. start_indices: [],
  9759. limit_indices: [],
  9760. strides: []
  9761. };
  9762. if (parser.parseOptionalLSquare()) {
  9763. while (parser.getToken().isNot(_.Token.r_square)) {
  9764. if (parser.getToken().is(_.Token.integer)) {
  9765. ranges.start_indices.push(parser.parseInteger());
  9766. }
  9767. parser.parseOptionalColon();
  9768. if (parser.getToken().is(_.Token.integer)) {
  9769. ranges.limit_indices.push(parser.parseInteger());
  9770. }
  9771. if (parser.parseOptionalColon()) {
  9772. if (parser.getToken().is(_.Token.integer)) {
  9773. ranges.strides.push(parser.parseInteger());
  9774. }
  9775. } else {
  9776. ranges.strides.push(1);
  9777. }
  9778. parser.parseOptionalComma();
  9779. }
  9780. parser.parseOptionalRSquare();
  9781. }
  9782. op.addAttribute('start_indices', ranges.start_indices);
  9783. op.addAttribute('limit_indices', ranges.limit_indices);
  9784. op.addAttribute('strides', ranges.strides);
  9785. }
  9786. // custom<CustomCallTarget>($call_target_name)
  9787. parseCustomCallTarget(parser, op, attrName) {
  9788. let target = null;
  9789. if (parser.getToken().is(_.Token.at_identifier)) {
  9790. target = parser.getToken().getSpelling().str();
  9791. parser.consumeToken(_.Token.at_identifier);
  9792. } else if (parser.getToken().is(_.Token.string)) {
  9793. target = parser.getToken().getSpelling().str();
  9794. parser.consumeToken(_.Token.string);
  9795. } else {
  9796. throw new mlir.Error(`Expected '@' or string for CustomCallTarget at ${parser.location()}`);
  9797. }
  9798. op.addAttribute(attrName || 'call_target_name', target);
  9799. }
  9800. // custom<VariadicOperandWithAttribute>($inputs)
  9801. parseVariadicOperandWithAttribute(parser, op, operands) {
  9802. while (parser.getToken().is(_.Token.percent_identifier)) {
  9803. const operand = parser.parseOperand();
  9804. if (parser.getToken().is(_.Token.l_brace)) {
  9805. operand.attributes = new Map();
  9806. parser.parseAttributeDict(operand.attributes);
  9807. }
  9808. operands.push(operand);
  9809. if (!parser.parseOptionalComma()) {
  9810. break;
  9811. }
  9812. }
  9813. }
  9814. parseReduceOp(parser, result, createDimensions, returnOpName) {
  9815. const unresolvedOperands = [];
  9816. const unresolvedInitOperands = [];
  9817. while (true) {
  9818. if (!parser.parseOptionalLParen()) {
  9819. break;
  9820. }
  9821. const operand = parser.parseOperand();
  9822. parser.parseKeyword('init');
  9823. parser.parseColon();
  9824. const initOperand = parser.parseOperand();
  9825. parser.parseRParen();
  9826. unresolvedOperands.push(operand);
  9827. unresolvedInitOperands.push(initOperand);
  9828. parser.parseOptionalComma();
  9829. }
  9830. const allUnresolved = unresolvedOperands.concat(unresolvedInitOperands);
  9831. if (parser.parseOptionalKeyword('applies')) {
  9832. const innerOpName = parser.parseCustomOperationName();
  9833. parser.parseKeyword('across');
  9834. parser.parseKeyword('dimensions');
  9835. parser.parseEqual();
  9836. parser.parseLSquare();
  9837. const dimensions = [];
  9838. while (parser.getToken().isNot(_.Token.r_square)) {
  9839. if (parser.getToken().is(_.Token.integer)) {
  9840. dimensions.push(parser.getToken().getSpelling().str());
  9841. parser.consumeToken(_.Token.integer);
  9842. } else {
  9843. throw new mlir.Error(`Expected integer dimension in reduce operation ${parser.location()}`);
  9844. }
  9845. if (!parser.parseOptionalComma() && parser.getToken().isNot(_.Token.r_square)) {
  9846. throw new mlir.Error(`Expected ',' or ']' in dimensions list ${parser.location()}`);
  9847. }
  9848. }
  9849. parser.parseRSquare();
  9850. result.addAttribute('dimensions', createDimensions(dimensions));
  9851. parser.parseOptionalAttrDict(result.attributes);
  9852. if (parser.parseOptionalColon()) {
  9853. const type = parser.parseType();
  9854. if (type instanceof _.FunctionType) {
  9855. parser.resolveOperands(allUnresolved, type.inputs, result.operands);
  9856. result.addTypes(type.results);
  9857. } else {
  9858. const types = Array.isArray(type) ? type : [type];
  9859. parser.resolveOperands(allUnresolved, allUnresolved.map((_, i) => types[i] || types[0]), result.operands);
  9860. if (parser.parseOptionalArrow()) {
  9861. result.addTypes(parser.parseFunctionResultTypes());
  9862. }
  9863. }
  9864. } else {
  9865. parser.resolveOperands(allUnresolved, allUnresolved.map(() => null), result.operands);
  9866. }
  9867. const region = { blocks: [] };
  9868. const block = { operations: [], arguments: [] };
  9869. let tensorType = null;
  9870. if (result.operands.length > 0 && result.operands[0].type) {
  9871. const operandType = result.operands[0].type;
  9872. if (operandType instanceof _.RankedTensorType || operandType instanceof _.UnrankedTensorType) {
  9873. tensorType = new _.RankedTensorType([], operandType.elementType);
  9874. }
  9875. }
  9876. block.arguments.push({ value: '%lhs', type: tensorType });
  9877. block.arguments.push({ value: '%rhs', type: tensorType });
  9878. const innerOp = new _.OperationState(null, innerOpName);
  9879. innerOp.operands.push(new _.Value('%lhs', tensorType));
  9880. innerOp.operands.push(new _.Value('%rhs', tensorType));
  9881. if (tensorType) {
  9882. innerOp.addTypes([tensorType]);
  9883. }
  9884. block.operations.push(_.Operation.create(innerOp));
  9885. const returnOp = new _.OperationState(null, this.getOperation(returnOpName));
  9886. returnOp.operands.push(new _.Value('%0', tensorType));
  9887. block.operations.push(_.Operation.create(returnOp));
  9888. region.blocks.push(block);
  9889. result.regions.push(region);
  9890. return true;
  9891. }
  9892. // Non-compact syntax: parse "across dimensions = [...] : type reducer (args) { ... }"
  9893. parser.parseKeyword('across');
  9894. parser.parseKeyword('dimensions');
  9895. parser.parseEqual();
  9896. parser.parseLSquare();
  9897. const dimensions = [];
  9898. while (parser.getToken().isNot(_.Token.r_square)) {
  9899. if (parser.getToken().is(_.Token.integer)) {
  9900. dimensions.push(parser.getToken().getSpelling().str());
  9901. parser.consumeToken(_.Token.integer);
  9902. }
  9903. parser.parseOptionalComma();
  9904. }
  9905. parser.parseRSquare();
  9906. result.addAttribute('dimensions', createDimensions(dimensions));
  9907. parser.parseOptionalAttrDict(result.attributes);
  9908. if (parser.parseOptionalColon()) {
  9909. const type = parser.parseType();
  9910. if (type instanceof _.FunctionType) {
  9911. parser.resolveOperands(allUnresolved, type.inputs, result.operands);
  9912. result.addTypes(type.results);
  9913. } else {
  9914. const types = Array.isArray(type) ? type : [type];
  9915. parser.resolveOperands(allUnresolved, types, result.operands);
  9916. }
  9917. }
  9918. parser.parseKeyword('reducer');
  9919. // Parse block arguments: (%lhs : type, %rhs : type) (%linit : type, %rinit : type)
  9920. const regionArgs = [];
  9921. while (parser.parseOptionalLParen()) {
  9922. while (parser.getToken().isNot(_.Token.r_paren)) {
  9923. const value = parser.parseOperand();
  9924. parser.parseColon();
  9925. const type = parser.parseType();
  9926. regionArgs.push({ value, type });
  9927. if (!parser.parseOptionalComma()) {
  9928. break;
  9929. }
  9930. }
  9931. parser.parseRParen();
  9932. }
  9933. const region = result.addRegion();
  9934. parser.parseRegion(region, regionArgs);
  9935. return true;
  9936. }
  9937. // Parse scan operation format: scan (%inputs) inits (%inits) dimension=0 { body } : types
  9938. parseScanOp(parser, result /*, returnOpName */) {
  9939. parser.parseLParen();
  9940. const unresolvedInputs = [];
  9941. while (parser.getToken().isNot(_.Token.r_paren)) {
  9942. unresolvedInputs.push(parser.parseOperand());
  9943. if (!parser.parseOptionalComma()) {
  9944. break;
  9945. }
  9946. }
  9947. parser.parseRParen();
  9948. parser.parseKeyword('inits');
  9949. parser.parseLParen();
  9950. const unresolvedInits = [];
  9951. while (parser.getToken().isNot(_.Token.r_paren)) {
  9952. unresolvedInits.push(parser.parseOperand());
  9953. if (!parser.parseOptionalComma()) {
  9954. break;
  9955. }
  9956. }
  9957. parser.parseRParen();
  9958. parser.parseKeyword('dimension');
  9959. parser.parseOptionalEqual();
  9960. const dimension = parser.getToken().getSpelling().str();
  9961. parser.consumeToken(_.Token.integer);
  9962. result.addAttribute('dimension', dimension);
  9963. // Parse optional attributes: is_reverse=true, is_associative=true
  9964. while (parser.parseOptionalComma() || parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'is_reverse' || parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'is_associative') {
  9965. if (parser.parseOptionalKeyword('is_reverse')) {
  9966. parser.parseOptionalEqual();
  9967. const value = parser.getToken().getSpelling().str();
  9968. parser.consumeToken(_.Token.bare_identifier);
  9969. result.addAttribute('is_reverse', value === 'true');
  9970. } else if (parser.parseOptionalKeyword('is_associative')) {
  9971. parser.parseOptionalEqual();
  9972. const value = parser.getToken().getSpelling().str();
  9973. parser.consumeToken(_.Token.bare_identifier);
  9974. result.addAttribute('is_associative', value === 'true');
  9975. }
  9976. }
  9977. const region = result.addRegion();
  9978. parser.parseRegion(region, undefined, true); // IsolatedFromAbove
  9979. // Parse types: : (input types, init types) -> (output types, carry types)
  9980. if (parser.parseOptionalColon()) {
  9981. const type = parser.parseType();
  9982. if (type instanceof _.FunctionType) {
  9983. const allUnresolved = unresolvedInputs.concat(unresolvedInits);
  9984. parser.resolveOperands(allUnresolved, type.inputs, result.operands);
  9985. result.addTypes(type.results);
  9986. }
  9987. }
  9988. return true;
  9989. }
  9990. };
  9991. _.StableHLODialect = class extends _.HLODialect {
  9992. constructor(operations) {
  9993. super(operations, 'stablehlo');
  9994. this.registerCustomDirective('ExponentMantissa', this.parseExponentMantissa.bind(this));
  9995. }
  9996. parseOperation(parser, result) {
  9997. if (result.op === 'stablehlo.constant') {
  9998. if (parser.parseOptionalLParen() && parser.parseOptionalRParen()) {
  9999. if (parser.parseOptionalLess()) {
  10000. result.propertiesAttr = parser.parseAttribute();
  10001. parser.parseGreater();
  10002. }
  10003. parser.parseOptionalAttrDict(result.attributes);
  10004. parser.parseColon();
  10005. parser.parseLParen();
  10006. parser.parseRParen();
  10007. parser.parseArrow();
  10008. const type = parser.parseType();
  10009. result.addTypes([type]);
  10010. } else {
  10011. // Custom form: {attrs} value : type
  10012. parser.parseOptionalAttrDict(result.attributes);
  10013. const value = parser.parseAttribute();
  10014. if (value) {
  10015. result.addAttribute('value', value);
  10016. }
  10017. const types = parser.parseOptionalColonTypeList();
  10018. if (types.length > 0) {
  10019. result.addTypes([types[0]]);
  10020. } else if (value && value.type) {
  10021. result.addTypes([value.type]);
  10022. }
  10023. }
  10024. return true;
  10025. }
  10026. if (result.op === 'stablehlo.while' && parser.getToken().is(_.Token.l_paren)) {
  10027. const unresolvedOperands = [];
  10028. parser.parseOptionalLParen();
  10029. while (parser.getToken().isNot(_.Token.r_paren)) {
  10030. parser.parseOperand(); // Skip block argument name
  10031. if (parser.parseOptionalEqual()) {
  10032. unresolvedOperands.push(parser.parseOperand());
  10033. }
  10034. parser.parseOptionalComma();
  10035. }
  10036. parser.parseRParen();
  10037. if (parser.parseOptionalColon()) {
  10038. const types = [];
  10039. while (!(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'cond') && !(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'attributes')) {
  10040. types.push(parser.parseType());
  10041. if (!parser.parseOptionalComma()) {
  10042. break;
  10043. }
  10044. }
  10045. parser.resolveOperands(unresolvedOperands, types, result.operands);
  10046. for (const type of types) {
  10047. result.addTypes([type]);
  10048. }
  10049. }
  10050. if (parser.parseOptionalKeyword('attributes')) {
  10051. if (parser.getToken().is(_.Token.l_brace)) {
  10052. parser.parseAttributeDict(result.attributes);
  10053. }
  10054. }
  10055. if (parser.parseOptionalKeyword('cond')) {
  10056. const cond = result.addRegion();
  10057. parser.parseRegion(cond);
  10058. }
  10059. if (parser.parseOptionalKeyword('do')) {
  10060. const body = result.addRegion();
  10061. parser.parseRegion(body);
  10062. }
  10063. return true;
  10064. }
  10065. if (result.op === 'stablehlo.reduce' && parser.getToken().is(_.Token.l_paren)) {
  10066. // stablehlo uses DenseI64ArrayAttr for dimensions (like b.getDenseI64ArrayAttr in ref impl)
  10067. return super.parseReduceOp(parser, result, (dims) => dims, 'stablehlo.return');
  10068. }
  10069. if (result.op === 'stablehlo.scan' && parser.getToken().is(_.Token.l_paren)) {
  10070. return super.parseScanOp(parser, result, 'stablehlo.return');
  10071. }
  10072. return super.parseOperation(parser, result);
  10073. }
  10074. parseType(parser, dialect) {
  10075. const mnemonic = parser.parseOptionalKeyword();
  10076. if (mnemonic === 'token') {
  10077. return new _.Type(`!${dialect}.token`);
  10078. }
  10079. throw new mlir.Error(`Unknown '${dialect}' type '${mnemonic}' ${parser.getNameLoc()}`);
  10080. }
  10081. parseExponentMantissa(parser, op, exponentAttr, mantissaAttr) {
  10082. const keyword = parser.getToken().getSpelling().str();
  10083. parser.consumeToken(_.Token.bare_identifier);
  10084. const match = /^e(\d+)m(\d+)$/.exec(keyword);
  10085. if (!match) {
  10086. throw new mlir.Error(`Expected exponent mantissa in format e#m#, got '${keyword}'`);
  10087. }
  10088. const exponent = parseInt(match[1], 10);
  10089. const mantissa = parseInt(match[2], 10);
  10090. op.addAttribute(exponentAttr, exponent);
  10091. op.addAttribute(mantissaAttr, mantissa);
  10092. }
  10093. };
  10094. _.VhloDialect = class extends _.Dialect {
  10095. constructor(operations) {
  10096. super(operations, 'vhlo');
  10097. this.registerCustomDirective('FunctionBody', this.parseFunctionBody.bind(this));
  10098. }
  10099. parseOperation(parser, result) {
  10100. if (result.op === 'vhlo.constant_v1') {
  10101. if (parser.getToken().is(_.Token.l_brace)) {
  10102. parser.parseAttributeDict(result.attributes);
  10103. }
  10104. const value = parser.parseAttribute();
  10105. if (value) {
  10106. result.addAttribute('value', value);
  10107. }
  10108. result.addTypes(parser.parseOptionalColonTypeList());
  10109. return true;
  10110. }
  10111. if (result.op === 'vhlo.return_v1') {
  10112. const unresolvedOperands = parser.parseOperandList();
  10113. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  10114. return true;
  10115. }
  10116. return super.parseOperation(parser, result);
  10117. }
  10118. parseFunctionBody(parser, result) {
  10119. parser.parseFunctionOp(result, false);
  10120. }
  10121. };
  10122. _.InterpreterDialect = class extends _.Dialect {
  10123. constructor(operations) {
  10124. super(operations, 'interpreter');
  10125. }
  10126. };
  10127. _.AffineDialect = class extends _.Dialect {
  10128. constructor(operations) {
  10129. super(operations, 'affine');
  10130. }
  10131. parseOperation(parser, result) {
  10132. if (result.op === 'affine.parallel') {
  10133. return this.parseParallelOp(parser, result);
  10134. }
  10135. // Special handling for affine.for - similar to scf.for but with affine expressions
  10136. if (result.op === 'affine.for') {
  10137. return this.parseForOp(parser, result);
  10138. }
  10139. // Special handling for affine.if - has condition before region
  10140. if (result.op === 'affine.if') {
  10141. // affine.if #set(dims)[symbols] [-> (type)] { region }
  10142. // Or: affine.if affine_set<(d0) : (constraint)>(dims)[symbols]
  10143. if (parser.getToken().is(_.Token.hash_identifier)) {
  10144. const condition = parser.parseAttribute();
  10145. result.addAttribute('condition', condition);
  10146. } else if (parser.consumeIf(_.Token.kw_affine_set)) {
  10147. const content = parser.skip('<');
  10148. result.addAttribute('condition', `affine_set${content}`);
  10149. }
  10150. const indexType = new _.IndexType();
  10151. if (parser.parseOptionalLParen()) {
  10152. while (!parser.parseOptionalRParen()) {
  10153. if (parser.getToken().is(_.Token.percent_identifier)) {
  10154. const operand = parser.parseOperand();
  10155. parser.resolveOperand(operand, indexType, result.operands);
  10156. }
  10157. parser.parseOptionalComma();
  10158. }
  10159. }
  10160. if (parser.parseOptionalLSquare()) {
  10161. while (!parser.parseOptionalRSquare()) {
  10162. if (parser.getToken().is(_.Token.percent_identifier)) {
  10163. const operand = parser.parseOperand();
  10164. parser.resolveOperand(operand, indexType, result.operands);
  10165. }
  10166. parser.parseOptionalComma();
  10167. }
  10168. }
  10169. result.addTypes(parser.parseOptionalArrowTypeList());
  10170. const region = result.addRegion();
  10171. parser.parseRegion(region);
  10172. if (parser.parseOptionalKeyword('else')) {
  10173. const elseRegion = {};
  10174. parser.parseRegion(elseRegion);
  10175. result.regions.push(elseRegion);
  10176. }
  10177. parser.parseOptionalAttrDict(result.attributes);
  10178. return true;
  10179. }
  10180. // Special handling for affine.apply, affine.min, and affine.max
  10181. if (result.op === 'affine.apply' || result.op === 'affine.min' || result.op === 'affine.max') {
  10182. if (parser.getToken().is(_.Token.hash_identifier) || parser.getToken().is(_.Token.kw_affine_map) || parser.getToken().is(_.Token.kw_affine_set)) {
  10183. const value = parser.parseAttribute();
  10184. result.addAttribute('map', value);
  10185. }
  10186. const indexType = new _.IndexType();
  10187. if (parser.getToken().is(_.Token.l_paren)) {
  10188. const unresolvedDims = parser.parseOperandList('paren');
  10189. parser.resolveOperands(unresolvedDims, unresolvedDims.map(() => indexType), result.operands);
  10190. }
  10191. const unresolvedSyms = parser.parseOperandList('optionalSquare');
  10192. parser.resolveOperands(unresolvedSyms, unresolvedSyms.map(() => indexType), result.operands);
  10193. parser.parseOptionalAttrDict(result.attributes);
  10194. result.addTypes([indexType]);
  10195. return true;
  10196. }
  10197. if (result.op === 'affine.store') {
  10198. return this.parseStoreOp(parser, result);
  10199. }
  10200. if (result.op === 'affine.load') {
  10201. return this.parseLoadOp(parser, result);
  10202. }
  10203. if (result.op === 'affine.vector_load') {
  10204. return this.parseVectorLoadOp(parser, result);
  10205. }
  10206. if (result.op === 'affine.vector_store') {
  10207. return this.parseVectorStoreOp(parser, result);
  10208. }
  10209. if (result.op === 'affine.prefetch') {
  10210. const memref = parser.parseOperand();
  10211. parser.skip('[');
  10212. parser.parseComma();
  10213. const rwSpecifier = parser.parseOptionalKeyword();
  10214. result.addAttribute('isWrite', rwSpecifier === 'write');
  10215. parser.parseComma();
  10216. parser.parseKeyword('locality');
  10217. parser.parseLess();
  10218. const locality = parser.getToken().getSpelling().str();
  10219. parser.consumeToken(_.Token.integer);
  10220. result.addAttribute('localityHint', locality);
  10221. parser.parseGreater();
  10222. parser.parseComma();
  10223. const cacheType = parser.parseOptionalKeyword();
  10224. result.addAttribute('isDataCache', cacheType === 'data');
  10225. parser.parseOptionalAttrDict(result.attributes);
  10226. const type = parser.parseColonType();
  10227. parser.resolveOperand(memref, type, result.operands);
  10228. return true;
  10229. }
  10230. // C++-only operation: affine.dma_start
  10231. // Defined in mlir/lib/Dialect/Affine/IR/AffineOps.cpp
  10232. if (result.op === 'affine.dma_start') {
  10233. const indexType = new _.IndexType();
  10234. const unresolvedOperands = [];
  10235. while (parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace)) {
  10236. if (parser.getToken().is(_.Token.percent_identifier)) {
  10237. unresolvedOperands.push(parser.parseOperand());
  10238. }
  10239. if (parser.getToken().is(_.Token.l_square)) {
  10240. parser.skip('[');
  10241. }
  10242. parser.parseOptionalComma();
  10243. }
  10244. parser.parseOptionalAttrDict(result.attributes);
  10245. const types = [];
  10246. if (parser.parseOptionalColon()) {
  10247. do {
  10248. types.push(parser.parseType());
  10249. } while (parser.parseOptionalComma());
  10250. }
  10251. // Resolve operands with types, use index for any operands beyond type count
  10252. const resolveTypes = unresolvedOperands.map((_, i) => i < types.length ? types[i] : indexType);
  10253. parser.resolveOperands(unresolvedOperands, resolveTypes, result.operands);
  10254. return true;
  10255. }
  10256. if (result.op === 'affine.dma_wait') {
  10257. const indexType = new _.IndexType();
  10258. const unresolvedOperands = [];
  10259. while (parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace)) {
  10260. if (parser.getToken().is(_.Token.percent_identifier)) {
  10261. unresolvedOperands.push(parser.parseOperand());
  10262. }
  10263. if (parser.getToken().is(_.Token.l_square)) {
  10264. parser.skip('[');
  10265. }
  10266. parser.parseOptionalComma();
  10267. }
  10268. parser.parseOptionalAttrDict(result.attributes);
  10269. let memrefType = null;
  10270. if (parser.parseOptionalColon()) {
  10271. memrefType = parser.parseType();
  10272. }
  10273. // First operand is tag (memref type), rest are indices (index type)
  10274. const resolveTypes = unresolvedOperands.map((_, i) => i === 0 ? memrefType : indexType);
  10275. parser.resolveOperands(unresolvedOperands, resolveTypes, result.operands);
  10276. return true;
  10277. }
  10278. return super.parseOperation(parser, result);
  10279. }
  10280. parseForOp(parser, result) {
  10281. const inductionVar = parser.parseOperand();
  10282. parser.parseOptionalLocationSpecifier();
  10283. parser.parseEqual();
  10284. this.parseAffineBound(parser, result, 'lowerBound');
  10285. parser.parseKeyword('to');
  10286. this.parseAffineBound(parser, result, 'upperBound');
  10287. if (parser.parseOptionalKeyword('step')) {
  10288. if (parser.getToken().is(_.Token.integer)) {
  10289. const step = parser.getToken().getSpelling().str();
  10290. parser.consumeToken(_.Token.integer);
  10291. result.addAttribute('step', step);
  10292. }
  10293. }
  10294. if (parser.parseOptionalKeyword('iter_args')) {
  10295. const unresolvedIterOperands = [];
  10296. if (parser.parseOptionalLParen()) {
  10297. while (!parser.parseOptionalRParen()) {
  10298. if (parser.getToken().is(_.Token.percent_identifier)) {
  10299. parser.parseOperand(); // iter arg (block arg)
  10300. }
  10301. if (parser.parseOptionalEqual()) {
  10302. if (parser.getToken().is(_.Token.percent_identifier)) {
  10303. unresolvedIterOperands.push(parser.parseOperand());
  10304. } else {
  10305. // Non-SSA values like constants - skip as they're not operands
  10306. parser.parseAttribute();
  10307. }
  10308. }
  10309. parser.parseOptionalComma();
  10310. }
  10311. }
  10312. const iterTypes = parser.parseOptionalArrowTypeList();
  10313. result.addTypes(iterTypes);
  10314. parser.resolveOperands(unresolvedIterOperands, iterTypes, result.operands);
  10315. }
  10316. if (parser.getToken().is(_.Token.l_brace)) {
  10317. const region = {};
  10318. parser.parseRegion(region);
  10319. if (region.blocks && region.blocks.length > 0) {
  10320. if (!region.blocks[0].arguments) {
  10321. region.blocks[0].arguments = [];
  10322. }
  10323. if (region.blocks[0].arguments.length > 0) {
  10324. region.blocks[0].arguments[0] = { value: inductionVar };
  10325. } else {
  10326. region.blocks[0].arguments.push({ value: inductionVar });
  10327. }
  10328. }
  10329. result.regions.push(region);
  10330. }
  10331. parser.parseOptionalAttrDict(result.attributes);
  10332. return true;
  10333. }
  10334. parseAffineBound(parser, op, boundName) {
  10335. // Parse affine bound following reference implementation in AffineOps.cpp parseBound()
  10336. // All affine operands have type index
  10337. const indexType = new _.IndexType();
  10338. // Try parsing SSA value first (shorthand for identity map)
  10339. if (parser.getToken().is(_.Token.percent_identifier)) {
  10340. const unresolved = parser.parseOperand();
  10341. parser.resolveOperands([unresolved], [indexType], op.operands);
  10342. const mapAttrName = boundName === 'lowerBound' ? 'lowerBoundMap' : 'upperBoundMap';
  10343. op.addAttribute(mapAttrName, 'symbol_identity');
  10344. return;
  10345. }
  10346. // Try parsing integer literal (shorthand for constant map)
  10347. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus)) {
  10348. const negate = parser.consumeIf(_.Token.minus);
  10349. let value = parser.parseInteger();
  10350. if (negate) {
  10351. value = -value;
  10352. }
  10353. const mapAttrName = boundName === 'lowerBound' ? 'lowerBoundMap' : 'upperBoundMap';
  10354. op.addAttribute(mapAttrName, value);
  10355. return;
  10356. }
  10357. if (!parser.parseOptionalKeyword('min')) {
  10358. parser.parseOptionalKeyword('max');
  10359. }
  10360. if (parser.getToken().is(_.Token.hash_identifier) || parser.getToken().is(_.Token.kw_affine_map)) {
  10361. const mapValue = parser.parseAttribute();
  10362. if (mapValue) {
  10363. const mapAttrName = boundName === 'lowerBound' ? 'lowerBoundMap' : 'upperBoundMap';
  10364. op.addAttribute(mapAttrName, mapValue);
  10365. // Parse dim and symbol operands in ()[...] or (...)
  10366. const unresolvedOperands = [];
  10367. if (parser.parseOptionalLParen()) {
  10368. while (!parser.parseOptionalRParen()) {
  10369. if (parser.getToken().is(_.Token.percent_identifier)) {
  10370. unresolvedOperands.push(parser.parseOperand());
  10371. }
  10372. parser.parseOptionalComma();
  10373. }
  10374. }
  10375. if (parser.parseOptionalLSquare()) {
  10376. while (!parser.parseOptionalRSquare()) {
  10377. if (parser.getToken().is(_.Token.percent_identifier)) {
  10378. unresolvedOperands.push(parser.parseOperand());
  10379. }
  10380. parser.parseOptionalComma();
  10381. }
  10382. }
  10383. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), op.operands);
  10384. return;
  10385. }
  10386. }
  10387. throw new mlir.Error(`Expected loop bound (SSA value, integer, or affine map) in affine.for ${parser.location()}`);
  10388. }
  10389. parseStoreOp(parser, result) {
  10390. let unresolvedValue = null;
  10391. if (parser.getToken().is(_.Token.percent_identifier)) {
  10392. unresolvedValue = parser.parseOperand();
  10393. }
  10394. // Note: attribute values are not operands
  10395. if (!parser.parseOptionalKeyword('to')) {
  10396. parser.parseOptionalComma();
  10397. }
  10398. const unresolvedAddress = parser.parseOperand();
  10399. parser.skip('[');
  10400. if (parser.parseOptionalColon()) {
  10401. const memrefType = parser.parseType();
  10402. // Value type is element type of memref
  10403. const valueType = memrefType.elementType || memrefType;
  10404. if (unresolvedValue) {
  10405. parser.resolveOperands([unresolvedValue], [valueType], result.operands);
  10406. }
  10407. parser.resolveOperands([unresolvedAddress], [memrefType], result.operands);
  10408. }
  10409. return true;
  10410. }
  10411. parseLoadOp(parser, result) {
  10412. const memref = parser.parseOperand();
  10413. parser.skip('[');
  10414. parser.parseOptionalAttrDict(result.attributes);
  10415. const type = parser.parseColonType();
  10416. parser.resolveOperand(memref, type, result.operands);
  10417. // Result type is element type of memref
  10418. result.addTypes([type.elementType || type]);
  10419. return true;
  10420. }
  10421. parseVectorLoadOp(parser, result) {
  10422. const memref = parser.parseOperand();
  10423. parser.skip('[');
  10424. parser.parseOptionalAttrDict(result.attributes);
  10425. if (parser.parseOptionalColon()) {
  10426. const memrefType = parser.parseType();
  10427. parser.resolveOperand(memref, memrefType, result.operands);
  10428. parser.parseComma();
  10429. const vectorType = parser.parseType();
  10430. result.addTypes([vectorType]);
  10431. } else {
  10432. parser.resolveOperand(memref, null, result.operands);
  10433. }
  10434. return true;
  10435. }
  10436. parseVectorStoreOp(parser, result) {
  10437. const value = parser.parseOperand();
  10438. parser.parseComma();
  10439. const memref = parser.parseOperand();
  10440. parser.skip('[');
  10441. parser.parseOptionalAttrDict(result.attributes);
  10442. if (parser.parseOptionalColon()) {
  10443. const memrefType = parser.parseType();
  10444. parser.parseComma();
  10445. const vectorType = parser.parseType();
  10446. // Resolve operands: value first, then memref
  10447. parser.resolveOperand(value, vectorType, result.operands);
  10448. parser.resolveOperand(memref, memrefType, result.operands);
  10449. } else {
  10450. parser.resolveOperand(value, null, result.operands);
  10451. parser.resolveOperand(memref, null, result.operands);
  10452. }
  10453. return true;
  10454. }
  10455. parseParallelOp(parser, result) {
  10456. const ivArgs = parser.parseArgumentList('paren', false);
  10457. const indexType = new _.IndexType();
  10458. for (const iv of ivArgs) {
  10459. iv.type = indexType;
  10460. }
  10461. if (!parser.parseOptionalEqual()) {
  10462. return false;
  10463. }
  10464. parser.skip('(');
  10465. if (!parser.parseOptionalKeyword('to')) {
  10466. return false;
  10467. }
  10468. parser.skip('(');
  10469. if (parser.parseOptionalKeyword('step')) {
  10470. parser.skip('(');
  10471. }
  10472. if (parser.parseOptionalKeyword('reduce')) {
  10473. parser.parseLParen();
  10474. while (parser.getToken().isNot(_.Token.r_paren)) {
  10475. if (parser.getToken().is(_.Token.string)) {
  10476. parser.consumeToken(_.Token.string);
  10477. }
  10478. if (!parser.parseOptionalComma()) {
  10479. break;
  10480. }
  10481. }
  10482. parser.parseRParen();
  10483. }
  10484. if (parser.parseOptionalArrow()) {
  10485. const resultTypes = [];
  10486. const resultAttrs = [];
  10487. parser.parseFunctionResultList(resultTypes, resultAttrs);
  10488. result.addTypes(resultTypes);
  10489. }
  10490. if (parser.getToken().is(_.Token.l_brace)) {
  10491. // Pass iv arguments to parseRegion - they become block arguments
  10492. const region = result.addRegion();
  10493. parser.parseRegion(region, ivArgs);
  10494. }
  10495. parser.parseOptionalAttrDict(result.attributes);
  10496. return true;
  10497. }
  10498. };
  10499. _.MemRefDialect = class extends _.Dialect {
  10500. constructor(operations) {
  10501. super(operations, 'memref');
  10502. this.registerCustomDirective('GlobalMemrefOpTypeAndInitialValue', this.parseGlobalMemrefOpTypeAndInitialValue.bind(this));
  10503. // AtomicRMWKindAttr can appear as bare id (addi) or string ("addi") in different test files
  10504. this.registerCustomAttribute('AtomicRMWKindAttr', this.parseAtomicRMWKindAttr.bind(this));
  10505. }
  10506. parseAtomicRMWKindAttr(parser, type) {
  10507. // Accept both bare identifier (addi) and string literal ("addi")
  10508. if (parser.getToken().is(_.Token.string)) {
  10509. const retVal = parser.getToken().getSpelling().str();
  10510. parser.consumeToken(_.Token.string);
  10511. return retVal;
  10512. }
  10513. if (parser.getToken().is(_.Token.bare_identifier) && type.values && type.values.includes(parser.getTokenSpelling().str())) {
  10514. const retVal = parser.getToken().getSpelling().str();
  10515. parser.consumeToken(_.Token.bare_identifier);
  10516. return retVal;
  10517. }
  10518. return null;
  10519. }
  10520. parseGlobalMemrefOpTypeAndInitialValue(parser, op, typeAttr = 'type', initialValueAttr = 'initial_value') {
  10521. const type = parser.parseType();
  10522. op.addAttribute(typeAttr, { value: type, type: 'type' });
  10523. if (parser.parseOptionalEqual()) {
  10524. if (parser.parseOptionalKeyword('uninitialized')) {
  10525. op.addAttribute(initialValueAttr, 'uninitialized');
  10526. } else {
  10527. // Pass the type to parseAttribute to suppress : type suffix parsing
  10528. const initialValue = parser.parseAttribute(type);
  10529. op.addAttribute(initialValueAttr, initialValue);
  10530. }
  10531. }
  10532. }
  10533. parseOperation(parser, result) {
  10534. if (result.op === 'memref.tensor_load') {
  10535. const unresolvedOperands = parser.parseOperandList();
  10536. const types = parser.parseOptionalColonTypeList();
  10537. parser.resolveOperands(unresolvedOperands, types, result.operands);
  10538. // Infer result tensor type from memref operand type
  10539. if (result.operands.length > 0 && result.operands[0].type) {
  10540. const memrefType = result.operands[0].type;
  10541. // Convert memref type to tensor type
  10542. if (memrefType instanceof _.MemRefType) {
  10543. result.addTypes([new _.RankedTensorType(memrefType.shape, memrefType.elementType, null)]);
  10544. } else if (memrefType instanceof _.UnrankedMemRefType) {
  10545. result.addTypes([new _.UnrankedTensorType(memrefType.elementType)]);
  10546. }
  10547. }
  10548. return true;
  10549. }
  10550. if (result.op === 'memref.store') {
  10551. result.compatibility = true;
  10552. return this.parseStoreOp(parser, result);
  10553. }
  10554. if (result.op === 'memref.alloca_scope') {
  10555. return this.parseAllocaScopeOp(parser, result);
  10556. }
  10557. if (result.op === 'memref.transpose') {
  10558. return this.parseTransposeOp(parser, result);
  10559. }
  10560. if (result.op === 'memref.generic_atomic_rmw') {
  10561. return this.parseGenericAtomicRMWOp(parser, result);
  10562. }
  10563. if (result.op === 'memref.prefetch') {
  10564. const memref = parser.parseOperand();
  10565. const indices = parser.parseOperandList('square');
  10566. parser.parseComma();
  10567. const readOrWrite = parser.getToken().getSpelling().str();
  10568. parser.consumeToken(_.Token.bare_identifier);
  10569. result.addAttribute('isWrite', readOrWrite === 'write');
  10570. parser.parseComma();
  10571. parser.parseKeyword('locality');
  10572. parser.parseLess();
  10573. const localityHint = parseInt(parser.getToken().getSpelling().str(), 10);
  10574. parser.consumeToken(_.Token.integer);
  10575. result.addAttribute('localityHint', localityHint);
  10576. parser.parseGreater();
  10577. parser.parseComma();
  10578. const cacheType = parser.getToken().getSpelling().str();
  10579. parser.consumeToken(_.Token.bare_identifier);
  10580. result.addAttribute('isDataCache', cacheType === 'data');
  10581. const type = parser.parseColonType();
  10582. parser.resolveOperand(memref, type, result.operands);
  10583. const indexType = new _.IndexType();
  10584. const indexTypes = indices.map(() => indexType);
  10585. parser.resolveOperands(indices, indexTypes, result.operands);
  10586. return true;
  10587. }
  10588. if (result.op === 'memref.dma_start') {
  10589. const srcMemRef = parser.parseOperand();
  10590. const srcIndices = parser.parseOperandList('square');
  10591. parser.parseComma();
  10592. const dstMemRef = parser.parseOperand();
  10593. const dstIndices = parser.parseOperandList('square');
  10594. parser.parseComma();
  10595. const numElements = parser.parseOperand();
  10596. parser.parseComma();
  10597. const tagMemRef = parser.parseOperand();
  10598. const tagIndices = parser.parseOperandList('square');
  10599. const strideInfo = [];
  10600. while (parser.parseOptionalComma() && parser.getToken().is(_.Token.percent_identifier)) {
  10601. strideInfo.push(parser.parseOperand());
  10602. }
  10603. const types = parser.parseColonTypeList();
  10604. const indexType = new _.IndexType();
  10605. parser.resolveOperand(srcMemRef, types[0], result.operands);
  10606. const srcIndexTypes = srcIndices.map(() => indexType);
  10607. parser.resolveOperands(srcIndices, srcIndexTypes, result.operands);
  10608. parser.resolveOperand(dstMemRef, types[1], result.operands);
  10609. const dstIndexTypes = dstIndices.map(() => indexType);
  10610. parser.resolveOperands(dstIndices, dstIndexTypes, result.operands);
  10611. parser.resolveOperand(numElements, indexType, result.operands);
  10612. parser.resolveOperand(tagMemRef, types[2], result.operands);
  10613. const tagIndexTypes = tagIndices.map(() => indexType);
  10614. parser.resolveOperands(tagIndices, tagIndexTypes, result.operands);
  10615. if (strideInfo.length > 0) {
  10616. const strideTypes = strideInfo.map(() => indexType);
  10617. parser.resolveOperands(strideInfo, strideTypes, result.operands);
  10618. }
  10619. return true;
  10620. }
  10621. return super.parseOperation(parser, result);
  10622. }
  10623. parseGenericAtomicRMWOp(parser, result) {
  10624. const memref = parser.parseOperand();
  10625. const indices = parser.parseOperandList('square');
  10626. parser.parseColon();
  10627. const memrefType = parser.parseType();
  10628. parser.resolveOperand(memref, memrefType, result.operands);
  10629. const indexType = new _.IndexType();
  10630. const indexTypes = indices.map(() => indexType);
  10631. parser.resolveOperands(indices, indexTypes, result.operands);
  10632. const region = result.addRegion();
  10633. parser.parseRegion(region);
  10634. parser.parseOptionalAttrDict(result.attributes);
  10635. if (memrefType && memrefType.elementType) {
  10636. result.addTypes([memrefType.elementType]);
  10637. }
  10638. return true;
  10639. }
  10640. parseTransposeOp(parser, result) {
  10641. const operand = parser.parseOperand();
  10642. const dims = parser.skip('(');
  10643. parser.parseArrow();
  10644. const results = parser.skip('(');
  10645. const permutation = `affine_map<${dims} -> ${results}>`;
  10646. result.addAttribute('permutation', permutation);
  10647. parser.parseOptionalAttrDict(result.attributes);
  10648. const srcType = parser.parseColonType();
  10649. parser.resolveOperand(operand, srcType, result.operands);
  10650. const dstType = parser.parseKeywordType('to');
  10651. result.addTypes([dstType]);
  10652. return true;
  10653. }
  10654. parseAllocaScopeOp(parser, result) {
  10655. const resultTypes = parser.parseOptionalArrowTypeList();
  10656. result.addTypes(resultTypes);
  10657. const region = result.addRegion();
  10658. parser.parseRegion(region);
  10659. parser.parseOptionalAttrDict(result.attributes);
  10660. return true;
  10661. }
  10662. parseStoreOp(parser, result) {
  10663. // or old: value to memref[indices] : type
  10664. let valueOperand = null;
  10665. if (parser.getToken().is(_.Token.percent_identifier)) {
  10666. valueOperand = parser.parseOperand();
  10667. } else {
  10668. // Non-standard: constant value - store as attribute
  10669. const value = parser.parseAttribute();
  10670. result.addAttribute('value', value);
  10671. }
  10672. // Accept either ',' (new) or 'to' (old)
  10673. if (!parser.parseOptionalKeyword('to')) {
  10674. parser.parseOptionalComma();
  10675. }
  10676. const memrefOperand = parser.parseOperand();
  10677. parser.skip('[');
  10678. if (parser.getToken().is(_.Token.l_brace)) {
  10679. parser.parseAttributeDict(result.attributes);
  10680. }
  10681. if (parser.parseOptionalColon()) {
  10682. const memrefType = parser.parseType();
  10683. // Value type is element type of memref
  10684. const valueType = memrefType.elementType || memrefType;
  10685. if (valueOperand) {
  10686. parser.resolveOperand(valueOperand, valueType, result.operands);
  10687. }
  10688. parser.resolveOperand(memrefOperand, memrefType, result.operands);
  10689. }
  10690. return true;
  10691. }
  10692. };
  10693. _.VectorDialect = class extends _.Dialect {
  10694. constructor(operations) {
  10695. super(operations, 'vector');
  10696. this.registerCustomAttribute('Vector_CombiningKindAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  10697. this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  10698. }
  10699. parseOperation(parser, result) {
  10700. if (result.op === 'vector.splat') {
  10701. const unresolvedOperands = parser.parseOperandList();
  10702. const types = parser.parseOptionalColonTypeList();
  10703. parser.resolveOperands(unresolvedOperands, types, result.operands);
  10704. result.addTypes(types);
  10705. return true;
  10706. }
  10707. if (result.op === 'vector.contract') {
  10708. if (parser.getToken().is(_.Token.l_brace)) {
  10709. parser.skip('{');
  10710. } else if (parser.getToken().is(_.Token.hash_identifier)) {
  10711. parser.consumeToken(_.Token.hash_identifier);
  10712. }
  10713. const unresolvedOperands = parser.parseOperandList();
  10714. parser.parseOptionalAttrDict(result.attributes);
  10715. const types = parser.parseColonTypeList();
  10716. parser.resolveOperands(unresolvedOperands, types, result.operands);
  10717. const resultType = parser.parseKeywordType('into');
  10718. result.addTypes([resultType]);
  10719. return true;
  10720. }
  10721. if (result.op === 'vector.mask') {
  10722. let mask = null;
  10723. let passthru = null;
  10724. let hasPassthru = false;
  10725. if (parser.getToken().is(_.Token.percent_identifier)) {
  10726. mask = parser.parseOperand();
  10727. }
  10728. if (parser.parseOptionalComma()) {
  10729. hasPassthru = true;
  10730. passthru = parser.parseOperand();
  10731. }
  10732. if (parser.getToken().is(_.Token.l_brace)) {
  10733. const region = result.addRegion();
  10734. parser.parseRegion(region);
  10735. }
  10736. parser.parseOptionalAttrDict(result.attributes);
  10737. const [maskType] = parser.parseOptionalColonTypeList();
  10738. const resultTypes = parser.parseOptionalArrowTypeList();
  10739. if (mask) {
  10740. parser.resolveOperand(mask, maskType, result.operands);
  10741. }
  10742. if (hasPassthru && passthru) {
  10743. parser.resolveOperand(passthru, resultTypes[0], result.operands);
  10744. }
  10745. result.addTypes(resultTypes);
  10746. return true;
  10747. }
  10748. if (result.op === 'vector.outerproduct') {
  10749. return this.parseOuterProductOp(parser, result);
  10750. }
  10751. if (result.op === 'vector.transfer_read' || result.op === 'vector.transfer_write') {
  10752. return this.parseTransferOp(parser, result);
  10753. }
  10754. if (result.op === 'vector.extract' && !result.isGeneric) {
  10755. result.compatibility = true; // compatibility
  10756. return this.parseExtractOp(parser, result);
  10757. }
  10758. return super.parseOperation(parser, result);
  10759. }
  10760. parseOuterProductOp(parser, result) {
  10761. const operandsInfo = parser.parseOperandList();
  10762. parser.parseOptionalAttrDict(result.attributes);
  10763. const tLHS = parser.parseColonType();
  10764. parser.parseComma();
  10765. const tRHS = parser.parseType();
  10766. const vLHS = tLHS instanceof _.VectorType ? tLHS : null;
  10767. const vRHS = tRHS instanceof _.VectorType ? tRHS : null;
  10768. let resType = null;
  10769. if (vRHS) {
  10770. const scalableDimsRes = [
  10771. vLHS.scalableDims ? vLHS.scalableDims[0] : false,
  10772. vRHS.scalableDims ? vRHS.scalableDims[0] : false
  10773. ];
  10774. resType = new _.VectorType([vLHS.shape[0], vRHS.shape[0]], vLHS.elementType, scalableDimsRes);
  10775. } else {
  10776. // Scalar RHS operand
  10777. const scalableDimsRes = [vLHS.scalableDims ? vLHS.scalableDims[0] : false];
  10778. resType = new _.VectorType([vLHS.shape[0]], vLHS.elementType, scalableDimsRes);
  10779. }
  10780. parser.resolveOperand(operandsInfo[0], tLHS, result.operands);
  10781. parser.resolveOperand(operandsInfo[1], tRHS, result.operands);
  10782. if (operandsInfo.length > 2) {
  10783. parser.resolveOperand(operandsInfo[2], resType, result.operands);
  10784. }
  10785. result.addTypes([resType]);
  10786. return true;
  10787. }
  10788. parseExtractOp(parser, result) {
  10789. // Old syntax (pre-2023): %r = vector.extract %v[0] : vector<4xf32>
  10790. // New syntax: %r = vector.extract %v[0] : f32 from vector<4xf32>
  10791. const unresolvedSource = parser.parseOperand();
  10792. const unresolvedDynIndices = [];
  10793. const indexType = new _.IndexType();
  10794. let numStaticIndices = 0;
  10795. if (parser.parseOptionalLSquare()) {
  10796. while (parser.getToken().isNot(_.Token.r_square)) {
  10797. const staticIndex = parser.parseOptionalInteger();
  10798. if (staticIndex !== null) {
  10799. numStaticIndices++;
  10800. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  10801. const dynIndex = parser.parseOperand();
  10802. unresolvedDynIndices.push(dynIndex);
  10803. } else {
  10804. break;
  10805. }
  10806. parser.parseOptionalComma();
  10807. }
  10808. parser.parseOptionalRSquare();
  10809. }
  10810. if (parser.getToken().is(_.Token.l_brace)) {
  10811. parser.parseAttributeDict(result.attributes);
  10812. }
  10813. if (parser.parseOptionalColon()) {
  10814. const resultType = parser.parseType();
  10815. if (parser.parseOptionalKeyword('from')) {
  10816. const sourceType = parser.parseType();
  10817. parser.resolveOperand(unresolvedSource, sourceType, result.operands);
  10818. result.addTypes([resultType]);
  10819. } else {
  10820. // Old syntax: the type after ':' is the source type
  10821. // Result type is inferred by removing dimensions based on indices
  10822. parser.resolveOperand(unresolvedSource, resultType, result.operands);
  10823. // Infer result type from source type and number of indices
  10824. const numIndices = numStaticIndices + unresolvedDynIndices.length;
  10825. if (resultType instanceof _.VectorType && numIndices > 0) {
  10826. const shape = resultType.shape.slice(numIndices);
  10827. if (shape.length === 0) {
  10828. // Scalar result
  10829. result.addTypes([resultType.elementType]);
  10830. } else {
  10831. const scalableDims = resultType.scalableDims ? resultType.scalableDims.slice(numIndices) : [];
  10832. result.addTypes([new _.VectorType(shape, resultType.elementType, scalableDims)]);
  10833. }
  10834. } else if (resultType instanceof _.VectorType) {
  10835. // No indices - result is the same as source
  10836. result.addTypes([resultType]);
  10837. }
  10838. }
  10839. parser.resolveOperands(unresolvedDynIndices, unresolvedDynIndices.map(() => indexType), result.operands);
  10840. }
  10841. return true;
  10842. }
  10843. parseTransferOp(parser, result) {
  10844. // or: vector.transfer_read %source[%i, %j, ...], %padding, %mask {attrs} : memref_type, vector_type
  10845. // or: vector.transfer_write %value, %dest[%i, %j, ...] {attrs} : vector_type, memref_type
  10846. // or: vector.transfer_write %value, %dest[%i, %j, ...], %mask {attrs} : vector_type, memref_type
  10847. const unresolvedFirst = parser.parseOperand();
  10848. const hasIndicesAfterFirst = parser.getToken().is(_.Token.l_square);
  10849. if (hasIndicesAfterFirst) {
  10850. parser.skip('[');
  10851. }
  10852. parser.parseOptionalComma();
  10853. const unresolvedSecond = parser.parseOperand();
  10854. if (!hasIndicesAfterFirst && parser.getToken().is(_.Token.l_square)) {
  10855. parser.skip('[');
  10856. }
  10857. // Optional mask parameter (third operand)
  10858. let unresolvedMask = null;
  10859. if (parser.parseOptionalComma()) {
  10860. unresolvedMask = parser.parseOperand();
  10861. }
  10862. if (parser.getToken().is(_.Token.l_brace)) {
  10863. parser.parseAttributeDict(result.attributes);
  10864. }
  10865. if (parser.parseOptionalColon()) {
  10866. const type1 = parser.parseType();
  10867. parser.parseOptionalComma();
  10868. const type2 = parser.parseType();
  10869. parser.resolveOperand(unresolvedFirst, type1, result.operands);
  10870. parser.resolveOperand(unresolvedSecond, type2, result.operands);
  10871. if (unresolvedMask) {
  10872. // Mask type would be a vector of i1, use type2 as approximation
  10873. parser.resolveOperand(unresolvedMask, type2, result.operands);
  10874. }
  10875. // For transfer_read, type2 is the result type
  10876. // For transfer_write to tensor (not memref), the result is the updated tensor
  10877. if (result.op === 'vector.transfer_read') {
  10878. result.addTypes([type2]);
  10879. } else if (result.op === 'vector.transfer_write' && type2 instanceof _.RankedTensorType) {
  10880. result.addTypes([type2]);
  10881. }
  10882. }
  10883. return true;
  10884. }
  10885. inferResultTypes(op, vars) {
  10886. if (op.op === 'vector.shuffle') {
  10887. const maskAttr = op.attributes.get('mask');
  10888. if (maskAttr instanceof _.DenseI64ArrayAttr && op.operands.length > 0) {
  10889. const v1Type = op.operands[0].type;
  10890. if (v1Type instanceof _.VectorType) {
  10891. const maskLength = maskAttr.value.length;
  10892. const trailingDims = v1Type.shape.slice(1);
  10893. const resultShape = [maskLength, ...trailingDims];
  10894. const resultType = new _.VectorType(resultShape, v1Type.elementType, v1Type.scalableDims ? [false, ...v1Type.scalableDims.slice(1)] : []);
  10895. op.addTypes([resultType]);
  10896. return;
  10897. }
  10898. }
  10899. }
  10900. if (op.op === 'vector.to_elements' && op.operands.length > 0) {
  10901. const vecType = op.operands[0].type;
  10902. if (vecType instanceof _.VectorType) {
  10903. const elType = vecType.elementType;
  10904. for (let i = 0; i < vecType.getNumElements(); i++) {
  10905. op.addTypes([elType]);
  10906. }
  10907. return;
  10908. }
  10909. }
  10910. super.inferResultTypes(op, vars);
  10911. }
  10912. };
  10913. _.TensorDialect = class extends _.Dialect {
  10914. constructor(operations) {
  10915. super(operations, 'tensor');
  10916. }
  10917. parseOperation(parser, result) {
  10918. if (result.op === 'tensor.expand_shape') {
  10919. // The new tensor.expand_shape format includes 'output_shape':
  10920. // $src $reassociation `output_shape` custom<DynamicIndexList>(...) attr-dict `:` type($src) `into` type($result)
  10921. // Old format (deprecated):
  10922. // $src $reassociation attr-dict `:` type($src) `into` type($result)
  10923. result.compatibility = true;
  10924. const unresolvedOperand = parser.parseOperand();
  10925. const reassociation = parser.parseAttribute();
  10926. result.addAttribute('reassociation', reassociation);
  10927. if (parser.parseOptionalKeyword('output_shape')) {
  10928. // New format: parse output_shape dynamic index list
  10929. this.parseDynamicIndexList(parser, result, ['$output_shape', '$static_output_shape']);
  10930. }
  10931. // Both formats: attr-dict `:` type($src) `into` type($result)
  10932. parser.parseOptionalAttrDict(result.attributes);
  10933. parser.parseColon();
  10934. const srcType = parser.parseType();
  10935. parser.resolveOperands([unresolvedOperand], [srcType], result.operands);
  10936. parser.parseKeyword('into');
  10937. const resultType = parser.parseType();
  10938. result.addTypes([resultType]);
  10939. return true;
  10940. }
  10941. return super.parseOperation(parser, result);
  10942. }
  10943. };
  10944. _.TorchDialect = class extends _.Dialect {
  10945. constructor(operations) {
  10946. super(operations, 'torch');
  10947. this.simpleTypes = new Set([
  10948. 'int', 'float', 'bool', 'str', 'none', 'Device', 'Generator',
  10949. 'qint8', 'quint8', 'qint16', 'qint32', 'quint4x2', 'quint2x4',
  10950. 'LinearParams', 'number', 'any'
  10951. ]);
  10952. }
  10953. parseType(parser, dialect) {
  10954. const mnemonic = parser.parseOptionalKeyword();
  10955. if (!mnemonic) {
  10956. return null;
  10957. }
  10958. let type = `!${dialect}.${mnemonic}`;
  10959. if (this.simpleTypes.has(mnemonic)) {
  10960. return new _.Type(type);
  10961. }
  10962. if (mnemonic === 'vtensor' || mnemonic === 'tensor' || mnemonic === 'list' || mnemonic === 'tuple' || mnemonic === 'union' || mnemonic === 'optional' || mnemonic === 'dict' || mnemonic.startsWith('nn.')) {
  10963. if (parser.getToken().is(_.Token.less)) {
  10964. const content = parser.skip('<');
  10965. type += content;
  10966. }
  10967. return new _.Type(type);
  10968. }
  10969. return null;
  10970. }
  10971. parseOperation(parser, result) {
  10972. if (result.op.startsWith('torch.constant.')) {
  10973. result.label = 'torch.constant';
  10974. } else if (result.op.startsWith('torch.aten.') || result.op.startsWith('torch.prim.') || result.op.startsWith('torch.prims.') || result.op.startsWith('torch.torchvision.')) {
  10975. result.label = `${result.op.split('.')[1]}.${result.op.split('.')[2]}`;
  10976. }
  10977. if (result.op === 'torch.constant.int') {
  10978. const value = parser.parseOptionalInteger();
  10979. if (value !== null) {
  10980. result.addAttribute('value', value);
  10981. }
  10982. parser.parseOptionalAttrDict(result.attributes);
  10983. result.addTypes([new _.Type('!torch.int')]);
  10984. return true;
  10985. }
  10986. if (result.op === 'torch.onnx.rotary_embedding') {
  10987. const unresolvedOperands = parser.parseOperandList();
  10988. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  10989. if (parser.parseOptionalArrow()) {
  10990. const resultType = parser.parseType();
  10991. result.addTypes([resultType]);
  10992. }
  10993. return true;
  10994. }
  10995. if (result.op === 'torch.bind_symbolic_shape') {
  10996. const unresolved = parser.parseOperand();
  10997. parser.parseOptionalComma();
  10998. const shapeSymbols = parser.parseOperandList('square');
  10999. parser.parseOptionalComma();
  11000. const shapeExpr = parser.parseAttribute();
  11001. result.addAttribute('shape_expressions', shapeExpr.value || shapeExpr);
  11002. parser.parseOptionalAttrDict(result.attributes);
  11003. let type = null;
  11004. if (parser.parseOptionalColon()) {
  11005. type = parser.parseType();
  11006. }
  11007. parser.resolveOperand(unresolved, type, result.operands);
  11008. for (const sym of shapeSymbols) {
  11009. parser.resolveOperand(sym, null, result.operands);
  11010. }
  11011. return true;
  11012. }
  11013. if (result.op === 'torch.initialize.global_slots') {
  11014. parser.parseOptionalAttrDict(result.attributes);
  11015. parser.parseLSquare();
  11016. const slotSymNames = [];
  11017. while (!parser.parseOptionalRSquare()) {
  11018. const slotSymName = parser.getToken().getSpelling().str();
  11019. parser.consumeToken(_.Token.at_identifier);
  11020. slotSymNames.push(slotSymName);
  11021. parser.parseLParen();
  11022. const unresolved = parser.parseOperand();
  11023. parser.parseColon();
  11024. const type = parser.parseType();
  11025. parser.resolveOperand(unresolved, type, result.operands);
  11026. parser.parseRParen();
  11027. }
  11028. result.addAttribute('slotSymNames', slotSymNames);
  11029. return true;
  11030. }
  11031. const opInfo = result.name.getRegisteredInfo();
  11032. if (opInfo.metadata.hasCustomAssemblyFormat && !opInfo.metadata.assemblyFormats) {
  11033. return this.parseDefaultTorchOp(parser, result);
  11034. }
  11035. return super.parseOperation(parser, result);
  11036. }
  11037. parseDefaultTorchOp(parser, result) {
  11038. const unresolvedOperands = parser.parseOperandList();
  11039. parser.parseOptionalAttrDict(result.attributes);
  11040. if (parser.parseOptionalColon()) {
  11041. parser.resolveOperands(unresolvedOperands, parser.parseTypeList(), result.operands);
  11042. } else {
  11043. for (const operand of unresolvedOperands) {
  11044. parser.resolveOperand(operand, null, result.operands);
  11045. }
  11046. }
  11047. if (parser.parseOptionalArrow()) {
  11048. // Handle both -> (type, type) and -> type, type syntaxes
  11049. const types = parser.getToken().is(_.Token.l_paren) ? parser.parseTypeListParens() : parser.parseTypeListNoParens();
  11050. result.addTypes(types);
  11051. }
  11052. if (parser.getToken().is(_.Token.l_brace)) {
  11053. const region = result.addRegion();
  11054. parser.parseRegion(region);
  11055. if (parser.parseOptionalKeyword('else') && parser.getToken().is(_.Token.l_brace)) {
  11056. const elseRegion = {};
  11057. parser.parseRegion(elseRegion);
  11058. result.regions.push(elseRegion);
  11059. }
  11060. }
  11061. return true;
  11062. }
  11063. };
  11064. _.IREEDialect = class extends _.Dialect {
  11065. constructor(operations, name) {
  11066. super(operations, name);
  11067. this.registerCustomDirective('DispatchEntryPoints', this.parseDispatchEntryPoints.bind(this));
  11068. this.registerCustomDirective('ShapedTiedResult', this.parseShapedTiedResult.bind(this));
  11069. this.registerCustomDirective('SymbolAlias', this.parseSymbolAlias.bind(this));
  11070. this.registerCustomDirective('TypeAlias', this.parseTypeAlias.bind(this));
  11071. this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));
  11072. this.registerCustomDirective('ShapedFunctionType', this.parseShapedFunctionType.bind(this));
  11073. }
  11074. parseShapedFunctionType(parser, op, unresolvedArguments /*, otherArgs */) {
  11075. const operandTypes = [];
  11076. parser.parseLParen();
  11077. if (parser.getToken().isNot(_.Token.r_paren)) {
  11078. do {
  11079. const type = parser.parseType();
  11080. if (type) {
  11081. operandTypes.push(type);
  11082. }
  11083. if (parser.getToken().is(_.Token.l_brace)) {
  11084. parser.skip('{');
  11085. }
  11086. } while (parser.parseOptionalComma());
  11087. }
  11088. parser.parseRParen();
  11089. parser.parseArrow();
  11090. const operands = unresolvedArguments || op.operands;
  11091. const resultTypes = [];
  11092. if (parser.parseOptionalLParen()) {
  11093. if (parser.getToken().isNot(_.Token.r_paren)) {
  11094. parser.parseShapedResultList(operands, operandTypes, resultTypes, null);
  11095. }
  11096. parser.parseRParen();
  11097. } else {
  11098. parser.parseShapedResultList(operands, operandTypes, resultTypes, null);
  11099. }
  11100. op.addTypes(resultTypes);
  11101. }
  11102. parseDispatchEntryPoints(parser, op, attrName = 'entry_points') {
  11103. const entryPoints = [];
  11104. if (parser.parseOptionalLBrace()) {
  11105. do {
  11106. if (parser.getToken().is(_.Token.at_identifier)) {
  11107. let symbol = parser.getToken().getSpelling().str();
  11108. parser.consumeToken(_.Token.at_identifier);
  11109. if (parser.getToken().is(_.Token.colon)) {
  11110. const curPointer = parser.getToken().loc.position;
  11111. parser.consumeToken(_.Token.colon);
  11112. if (parser.consumeIf(_.Token.colon)) {
  11113. if (parser.getToken().is(_.Token.at_identifier)) {
  11114. const nested = parser.getToken().getSpelling().str();
  11115. parser.consumeToken(_.Token.at_identifier);
  11116. symbol += `::${nested}`;
  11117. }
  11118. } else {
  11119. parser.resetToken(curPointer);
  11120. }
  11121. }
  11122. entryPoints.push(symbol);
  11123. }
  11124. } while (parser.parseOptionalComma());
  11125. parser.parseRBrace();
  11126. } else if (parser.getToken().is(_.Token.at_identifier)) {
  11127. let symbol = parser.getToken().getSpelling().str();
  11128. parser.consumeToken(_.Token.at_identifier);
  11129. if (parser.getToken().is(_.Token.colon)) {
  11130. const curPointer = parser.getToken().loc.position;
  11131. parser.consumeToken(_.Token.colon);
  11132. if (parser.consumeIf(_.Token.colon)) {
  11133. if (parser.getToken().is(_.Token.at_identifier)) {
  11134. const nested = parser.getToken().getSpelling().str();
  11135. parser.consumeToken(_.Token.at_identifier);
  11136. symbol += `::${nested}`;
  11137. }
  11138. } else {
  11139. parser.resetToken(curPointer);
  11140. }
  11141. }
  11142. entryPoints.push(symbol);
  11143. }
  11144. const value = entryPoints.length === 1 ? entryPoints[0] : entryPoints;
  11145. op.addAttribute(attrName, value);
  11146. }
  11147. parseShapedTiedResult(parser, op /*, args */) {
  11148. // or just: type{dims}
  11149. if (parser.getToken().is(_.Token.percent_identifier)) {
  11150. parser.parseOperand(); // tiedOperand - parsed but not stored in OperationState
  11151. parser.parseKeyword('as');
  11152. }
  11153. const resultType = parser.parseType();
  11154. op.types.push(resultType); // Only add the type
  11155. if (parser.parseOptionalLBrace()) {
  11156. const indexType = new _.IndexType();
  11157. while (parser.getToken().isNot(_.Token.r_brace)) {
  11158. if (parser.getToken().is(_.Token.percent_identifier)) {
  11159. const dim = parser.parseOperand();
  11160. parser.resolveOperand(dim, indexType, op.operands);
  11161. parser.parseOptionalComma();
  11162. } else {
  11163. break;
  11164. }
  11165. }
  11166. parser.parseRBrace();
  11167. }
  11168. }
  11169. parseSymbolAlias(parser, op, symNameAttr, aliasAttr) {
  11170. const alias = parser.getToken().getSpelling().str();
  11171. parser.consumeToken(_.Token.at_identifier);
  11172. let symName = alias;
  11173. if (parser.parseOptionalKeyword('as')) {
  11174. if (parser.parseOptionalLParen()) {
  11175. if (parser.getToken().is(_.Token.string)) {
  11176. symName = parser.getToken().getSpelling().str();
  11177. parser.consumeToken(_.Token.string);
  11178. } else if (parser.getToken().is(_.Token.at_identifier)) {
  11179. symName = parser.getToken().getSpelling().str();
  11180. parser.consumeToken(_.Token.at_identifier);
  11181. }
  11182. parser.parseOptionalRParen();
  11183. }
  11184. }
  11185. if (symNameAttr && aliasAttr) {
  11186. op.addAttribute(symNameAttr, symName);
  11187. op.addAttribute(aliasAttr, alias);
  11188. }
  11189. }
  11190. parseTypeAlias(parser, op, encodingAttrName, typeArg) {
  11191. const encodingType = parser.parseType();
  11192. let storageType = encodingType;
  11193. if (parser.parseOptionalKeyword('as')) {
  11194. storageType = parser.parseType();
  11195. }
  11196. if (encodingAttrName) {
  11197. op.addAttribute(encodingAttrName, encodingType);
  11198. }
  11199. if (!Array.isArray(typeArg)) {
  11200. throw new mlir.Error(`Invalid argument 'typeArg'.`);
  11201. }
  11202. if (typeArg.length > 0) {
  11203. typeArg[0] = storageType;
  11204. } else {
  11205. typeArg.push(storageType);
  11206. }
  11207. }
  11208. parseWorkgroupCountRegion(parser, result) {
  11209. if (!(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'workgroups')) {
  11210. return;
  11211. }
  11212. parser.parseKeyword('workgroups');
  11213. const region = { blocks: [] };
  11214. const block = { arguments: [], operations: [] };
  11215. if (parser.parseOptionalLParen()) {
  11216. while (parser.getToken().isNot(_.Token.r_paren)) {
  11217. const arg = parser.parseOperand();
  11218. if (parser.parseOptionalColon()) {
  11219. arg.type = parser.parseType();
  11220. }
  11221. block.arguments.push(arg);
  11222. if (!parser.parseOptionalComma()) {
  11223. break;
  11224. }
  11225. }
  11226. parser.parseRParen();
  11227. }
  11228. if (parser.parseOptionalArrow()) {
  11229. parser.parseLParen();
  11230. while (parser.getToken().isNot(_.Token.r_paren)) {
  11231. parser.parseType();
  11232. if (!parser.parseOptionalComma()) {
  11233. break;
  11234. }
  11235. }
  11236. parser.parseRParen();
  11237. }
  11238. if (parser.parseOptionalLBrace()) {
  11239. while (parser.getToken().isNot(_.Token.r_brace)) {
  11240. const innerOp = parser.parseOperation();
  11241. if (innerOp) {
  11242. block.operations.push(innerOp);
  11243. }
  11244. if (parser.getToken().is(_.Token.r_brace)) {
  11245. break;
  11246. }
  11247. }
  11248. parser.parseRBrace();
  11249. }
  11250. region.blocks.push(block);
  11251. result.regions.push(region);
  11252. }
  11253. };
  11254. _.HALDialect = class extends _.IREEDialect {
  11255. constructor(operations) {
  11256. super(operations, 'hal');
  11257. this.simpleTypes = new Set(['allocator', 'buffer', 'buffer_view', 'channel', 'command_buffer', 'descriptor_set', 'descriptor_set_layout', 'device', 'event', 'executable', 'executable_layout', 'fence', 'file', 'semaphore']);
  11258. this.registerCustomAttribute('HAL_PipelineLayoutAttr', this.parsePipelineLayoutAttr.bind(this));
  11259. this.registerCustomDirective('ExportConditionRegion', this.parseExportConditionRegion.bind(this));
  11260. this.registerCustomDirective('TargetConditionObjects', this.parseTargetConditionObjects.bind(this));
  11261. this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));
  11262. }
  11263. parseType(parser, dialect) {
  11264. const typeName = parser.parseOptionalKeyword();
  11265. if (!typeName) {
  11266. return null;
  11267. }
  11268. if (this.simpleTypes.has(typeName)) {
  11269. // Note: !hal.buffer{%size} syntax is handled by custom<SizeAwareType> directive,
  11270. // not by the type parser. The type parser just returns the base type.
  11271. return new _.Type(`!${dialect}.${typeName}`);
  11272. }
  11273. return null;
  11274. }
  11275. parseOperation(parser, result) {
  11276. const opInfo = result.name.getRegisteredInfo();
  11277. if (result.op === 'hal.tensor.cast') {
  11278. const unresolvedOperands = parser.parseOperandList();
  11279. if (parser.parseOptionalColon()) {
  11280. const type = parser.parseType();
  11281. parser.resolveOperands(unresolvedOperands, [type], result.operands);
  11282. } else {
  11283. for (const operand of unresolvedOperands) {
  11284. parser.resolveOperand(operand, null, result.operands);
  11285. }
  11286. }
  11287. if (parser.parseOptionalArrow()) {
  11288. const types = parser.parseFunctionResultTypes();
  11289. result.addTypes(types);
  11290. }
  11291. return true;
  11292. }
  11293. if (result.op === 'hal.constant') {
  11294. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  11295. const value = parser.parseAttribute();
  11296. result.addAttribute('value', value.value === undefined ? value : value.value);
  11297. result.addTypes(parser.parseOptionalColonTypeList());
  11298. return true;
  11299. }
  11300. if (result.op === 'hal.device.switch') {
  11301. if (parser.parseOptionalLess()) {
  11302. while (!parser.parseOptionalGreater()) {
  11303. const operand = parser.parseOperand();
  11304. let type = null;
  11305. if (parser.parseOptionalColon()) {
  11306. type = parser.parseType();
  11307. }
  11308. parser.resolveOperand(operand, type, result.operands);
  11309. parser.parseOptionalComma();
  11310. }
  11311. }
  11312. if (parser.parseOptionalArrow() || parser.parseOptionalColon()) {
  11313. const resultType = parser.parseType();
  11314. result.types = [resultType];
  11315. }
  11316. while (parser.getToken().is(_.Token.hash_identifier)) {
  11317. const region = {};
  11318. const caseAttr = parser.parseAttribute();
  11319. region.caseAttribute = caseAttr;
  11320. if (parser.getToken().is(_.Token.l_brace)) {
  11321. parser.parseRegion(region);
  11322. }
  11323. result.regions.push(region);
  11324. parser.parseOptionalComma();
  11325. }
  11326. return true;
  11327. }
  11328. if (result.op === 'hal.executable.constant.block') {
  11329. if (parser.parseOptionalLParen()) {
  11330. while (parser.getToken().isNot(_.Token.r_paren)) {
  11331. if (parser.getToken().is(_.Token.percent_identifier)) {
  11332. const arg = parser.parseOperand();
  11333. parser.parseColon();
  11334. const type = parser.parseType();
  11335. parser.resolveOperand(arg, type, result.operands);
  11336. }
  11337. if (!parser.parseOptionalComma()) {
  11338. break;
  11339. }
  11340. }
  11341. parser.parseRParen();
  11342. }
  11343. if (parser.parseOptionalArrow()) {
  11344. const resultTypes = parser.parseFunctionResultTypes();
  11345. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType([], resultTypes)));
  11346. }
  11347. if (parser.parseOptionalKeyword('as')) {
  11348. if (parser.getToken().is(_.Token.l_paren)) {
  11349. parser.parseLParen();
  11350. const keys = [];
  11351. while (parser.getToken().isNot(_.Token.r_paren)) {
  11352. if (parser.getToken().is(_.Token.string)) {
  11353. keys.push(parser.getToken().getSpelling().str());
  11354. parser.consumeToken(_.Token.string);
  11355. }
  11356. if (!parser.parseOptionalComma()) {
  11357. break;
  11358. }
  11359. }
  11360. parser.parseRParen();
  11361. result.addAttribute('keys', keys);
  11362. } else if (parser.getToken().is(_.Token.string)) {
  11363. const key = parser.getToken().getSpelling().str();
  11364. parser.consumeToken(_.Token.string);
  11365. result.addAttribute('keys', [key]);
  11366. }
  11367. }
  11368. if (parser.getToken().is(_.Token.l_brace)) {
  11369. const region = result.addRegion();
  11370. parser.parseRegion(region);
  11371. }
  11372. return true;
  11373. }
  11374. // Handle hal.executable.create with both old (layouts) and new (affinity) syntax
  11375. if (result.op === 'hal.executable.create') {
  11376. result.compatibility = true;
  11377. const inputNames = new Set(opInfo.metadata.operands.map((input) => input.name));
  11378. while (parser.getToken().is(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.kw_loc)) {
  11379. const paramName = parser.getToken().getSpelling().str();
  11380. parser.consumeToken(_.Token.bare_identifier);
  11381. if (parser.parseOptionalLParen()) {
  11382. if (inputNames.has(paramName) && parser.getToken().is(_.Token.percent_identifier)) {
  11383. const operand = parser.parseOperand();
  11384. let operandType = null;
  11385. if (parser.parseOptionalColon()) {
  11386. operandType = parser.parseType();
  11387. }
  11388. parser.parseRParen();
  11389. parser.resolveOperand(operand, operandType, result.operands);
  11390. } else if (inputNames.has(paramName) && parser.getToken().is(_.Token.l_square)) {
  11391. parser.parseLSquare();
  11392. while (parser.getToken().isNot(_.Token.r_square)) {
  11393. if (parser.getToken().is(_.Token.percent_identifier)) {
  11394. const operand = parser.parseOperand();
  11395. parser.resolveOperand(operand, null, result.operands);
  11396. }
  11397. parser.parseOptionalComma();
  11398. }
  11399. parser.parseRSquare();
  11400. parser.parseRParen();
  11401. } else {
  11402. let parenDepth = 1;
  11403. let paramValue = '';
  11404. while (parenDepth > 0 && parser.getToken().isNot(_.Token.eof)) {
  11405. if (parser.getToken().is(_.Token.l_paren)) {
  11406. parenDepth++;
  11407. paramValue += parser.getToken().getSpelling().str();
  11408. parser.consumeToken();
  11409. } else if (parser.getToken().is(_.Token.r_paren)) {
  11410. parenDepth--;
  11411. if (parenDepth > 0) {
  11412. paramValue += parser.getToken().getSpelling().str();
  11413. parser.consumeToken();
  11414. } else {
  11415. parser.parseRParen();
  11416. }
  11417. } else {
  11418. paramValue += parser.getToken().getSpelling().str();
  11419. parser.consumeToken();
  11420. }
  11421. }
  11422. // Normalize old 'layouts' parameter to 'affinity' for consistency
  11423. const normalizedName = paramName === 'layouts' ? 'affinity' : paramName;
  11424. result.addAttribute(normalizedName, paramValue);
  11425. }
  11426. } else {
  11427. break;
  11428. }
  11429. }
  11430. result.addTypes(parser.parseOptionalColonTypeList());
  11431. return true;
  11432. }
  11433. // Handle operations with <%operand : type> syntax and/or named parameters
  11434. // e.g., hal.allocator.compute_size<%allocator : !hal.allocator> shape([...]) type(...) encoding(...) : index
  11435. // or hal.executable_layout.lookup device(%device : !hal.device) layouts([[...]]) : !hal.executable_layout
  11436. // Exclude hal.executable, hal.interface, and hal.device.switch which have special handling
  11437. if ((result.op.startsWith('hal.allocator.') || result.op.startsWith('hal.buffer.') || result.op.startsWith('hal.buffer_view.') ||
  11438. result.op.startsWith('hal.command_buffer.') || result.op.startsWith('hal.executable_layout') ||
  11439. result.op.startsWith('hal.executable.') || result.op.startsWith('hal.descriptor_set_layout') ||
  11440. result.op.startsWith('hal.device.')) &&
  11441. result.op !== 'hal.device.allocator' &&
  11442. result.op !== 'hal.buffer_view.buffer' &&
  11443. result.op !== 'hal.executable' &&
  11444. result.op !== 'hal.interface' &&
  11445. result.op !== 'hal.device.switch' &&
  11446. result.op !== 'hal.device.memoize' &&
  11447. result.op !== 'hal.command_buffer.execution_barrier' &&
  11448. result.op !== 'hal.executable.entry_point' &&
  11449. result.op !== 'hal.executable.variant' &&
  11450. result.op !== 'hal.executable.lookup' &&
  11451. result.op !== 'hal.interface.binding' &&
  11452. result.op !== 'hal.executable.create' &&
  11453. result.op !== 'hal.executable.export' &&
  11454. result.op !== 'hal.executable.binary' &&
  11455. result.op !== 'hal.executable.source' &&
  11456. result.op !== 'hal.executable.condition' &&
  11457. result.op !== 'hal.executable.constant.block' &&
  11458. result.op !== 'hal.executable.constant.load') {
  11459. if (result.op === 'hal.allocator.allocate' || result.op === 'hal.command_buffer.create' || result.op === 'hal.buffer_view.create' || result.op === 'hal.command_buffer.device' || result.op === 'hal.command_buffer.dispatch' || result.op === 'hal.device.query') {
  11460. result.compatibility = true;
  11461. }
  11462. if (parser.parseOptionalLess()) {
  11463. while (!parser.parseOptionalGreater()) {
  11464. const operand = parser.parseOperand();
  11465. let type = null;
  11466. if (parser.parseOptionalColon()) {
  11467. type = parser.parseType();
  11468. }
  11469. parser.resolveOperand(operand, type, result.operands);
  11470. parser.parseOptionalComma();
  11471. }
  11472. }
  11473. // Also handle bracket expressions between parameters like layout(...)[%c0]
  11474. // Stop when we hit a colon (result type) or something that doesn't look like a parameter
  11475. // Named parameters don't have dots, so if we see an id with a dot, it's likely the next operation
  11476. // Also exclude common operation keywords that shouldn't be treated as parameters
  11477. const notParameterNames = new Set(['br', 'cond_br', 'return', 'yield', 'call', 'unreachable', 'assert']);
  11478. while (parser.getToken().is(_.Token.l_square) || (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() !== 'attributes' && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.kw_loc) && parser.getTokenSpelling().str() && parser.getTokenSpelling().str().indexOf('.') === -1 && !notParameterNames.has(parser.getTokenSpelling().str()))) {
  11479. if (parser.getToken().is(_.Token.l_square)) {
  11480. parser.skip('[');
  11481. continue;
  11482. }
  11483. const paramName = parser.getToken().getSpelling().str();
  11484. parser.consumeToken(_.Token.bare_identifier);
  11485. if (parser.parseOptionalLParen()) {
  11486. // Check if this named parameter is actually an input from the operation metadata
  11487. const inputNames = new Set((opInfo.metadata && opInfo.metadata.operands || []).map((i) => i.name));
  11488. if (inputNames.has(paramName) && parser.getToken().is(_.Token.percent_identifier)) {
  11489. const operand = parser.parseOperand();
  11490. let operandType = null;
  11491. if (parser.parseOptionalColon()) {
  11492. operandType = parser.parseType();
  11493. }
  11494. parser.parseRParen();
  11495. parser.resolveOperand(operand, operandType, result.operands);
  11496. } else if (inputNames.has(paramName) && parser.getToken().is(_.Token.l_square)) {
  11497. parser.parseLSquare();
  11498. while (parser.getToken().isNot(_.Token.r_square)) {
  11499. if (parser.getToken().is(_.Token.percent_identifier)) {
  11500. const operand = parser.parseOperand();
  11501. parser.resolveOperand(operand, null, result.operands);
  11502. }
  11503. parser.parseOptionalComma();
  11504. }
  11505. parser.parseRSquare();
  11506. parser.parseRParen();
  11507. } else {
  11508. let parenDepth = 1;
  11509. let paramValue = '';
  11510. while (parenDepth > 0 && parser.getToken().isNot(_.Token.eof)) {
  11511. if (parser.getToken().is(_.Token.l_paren)) {
  11512. parenDepth++;
  11513. paramValue += parser.getToken().getSpelling().str();
  11514. parser.consumeToken();
  11515. } else if (parser.getToken().is(_.Token.r_paren)) {
  11516. parenDepth--;
  11517. if (parenDepth > 0) {
  11518. paramValue += parser.getToken().getSpelling().str();
  11519. parser.consumeToken();
  11520. } else {
  11521. parser.parseRParen();
  11522. }
  11523. } else {
  11524. paramValue += parser.getToken().getSpelling().str();
  11525. parser.consumeToken();
  11526. }
  11527. }
  11528. result.addAttribute(paramName, paramValue);
  11529. }
  11530. } else {
  11531. // Not a named parameter - we've consumed an id token that doesn't belong to us
  11532. // This shouldn't happen with proper MLIR, but break gracefully
  11533. break;
  11534. }
  11535. }
  11536. result.addTypes(parser.parseOptionalColonTypeList());
  11537. // Handle old IREE format: !hal.buffer{%size} where {%size} follows the type
  11538. if (parser.getToken().is(_.Token.l_brace)) {
  11539. parser.skip('{');
  11540. }
  11541. if (parser.parseOptionalEqual()) {
  11542. const value = parser.parseAttribute();
  11543. result.addAttribute('default', value.value);
  11544. }
  11545. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  11546. return true;
  11547. }
  11548. if (result.op === 'hal.executable.condition' || result.op === 'hal.executable.constant.block') {
  11549. const sig = parser.parseFunctionSignatureWithArguments(false);
  11550. const argTypes = sig.arguments.map((a) => a.type);
  11551. const type = new _.FunctionType(argTypes, sig.resultTypes);
  11552. result.addAttribute('function_type', new _.TypeAttrOf(type));
  11553. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  11554. if (parser.getToken().is(_.Token.l_brace)) {
  11555. const region = result.addRegion();
  11556. parser.parseRegion(region, sig.arguments);
  11557. }
  11558. return true;
  11559. }
  11560. // Handle operations with visibility + symbol (similar to flow dialect)
  11561. if (result.op === 'hal.executable' || result.op === 'hal.executable.source' || result.op === 'hal.interface' || result.op === 'hal.executable.binary') {
  11562. result.compatibility = true;
  11563. this.parseSymbolVisibility(parser, result);
  11564. if (parser.getToken().is(_.Token.at_identifier)) {
  11565. parser.parseSymbolName('sym_name', result.attributes);
  11566. }
  11567. if (parser.parseOptionalKeyword('attributes')) {
  11568. parser.parseAttributeDict(result.attributes);
  11569. }
  11570. if (parser.getToken().is(_.Token.l_brace)) {
  11571. const region = result.addRegion();
  11572. parser.parseRegion(region);
  11573. }
  11574. return true;
  11575. }
  11576. // Handle hal.interface.binding.subspan with old syntax (symbol reference)
  11577. // Old syntax: hal.interface.binding.subspan @io::@binding[operand] : type
  11578. // New syntax: hal.interface.binding.subspan layout(...) binding(...) : type
  11579. if (result.op === 'hal.interface.binding.subspan' && parser.getToken().is(_.Token.at_identifier)) {
  11580. result.compatibility = true;
  11581. // Old syntax - parse symbol reference and bracket expression
  11582. const symbolRef = parser.getToken().getSpelling().str();
  11583. parser.consumeToken(_.Token.at_identifier);
  11584. result.addAttribute('layout', symbolRef);
  11585. const unresolvedOperands = [];
  11586. const indexType = new _.IndexType();
  11587. if (parser.parseOptionalLSquare()) {
  11588. while (!parser.parseOptionalRSquare()) {
  11589. if (parser.getToken().is(_.Token.percent_identifier)) {
  11590. const operand = parser.parseOperand();
  11591. unresolvedOperands.push(operand);
  11592. } else {
  11593. parser.consumeToken();
  11594. }
  11595. parser.parseOptionalComma();
  11596. }
  11597. }
  11598. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), result.operands);
  11599. if (parser.parseOptionalColon()) {
  11600. const type = parser.parseType();
  11601. if (type) {
  11602. result.addTypes([type]);
  11603. }
  11604. if (parser.parseOptionalLBrace()) {
  11605. const dynamicDimOperands = [];
  11606. if (parser.getToken().isNot(_.Token.r_brace)) {
  11607. do {
  11608. const dimOperand = parser.parseOperand();
  11609. dynamicDimOperands.push(dimOperand);
  11610. } while (parser.parseOptionalComma());
  11611. }
  11612. parser.parseRBrace();
  11613. parser.resolveOperands(dynamicDimOperands, dynamicDimOperands.map(() => indexType), result.operands);
  11614. }
  11615. }
  11616. return true;
  11617. }
  11618. // Handle operations with named parameters: hal.interface.binding, hal.executable.variant, etc.
  11619. if (result.op === 'hal.interface.binding' || result.op === 'hal.executable.variant' || result.op === 'hal.executable.entry_point' || result.op === 'hal.executable.export') {
  11620. result.compatibility = true;
  11621. this.parseSymbolVisibility(parser, result);
  11622. if (parser.getToken().is(_.Token.at_identifier)) {
  11623. parser.parseSymbolName('sym_name', result.attributes);
  11624. parser.parseOptionalComma();
  11625. }
  11626. while (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() !== 'attributes' && parser.getToken().isNot(_.Token.l_brace) && parser.getToken().isNot(_.Token.kw_loc)) {
  11627. const tokenValue = parser.getTokenSpelling().str();
  11628. if (tokenValue && tokenValue.includes('.')) {
  11629. break;
  11630. }
  11631. const paramName = parser.getToken().getSpelling().str();
  11632. parser.consumeToken(_.Token.bare_identifier);
  11633. if (paramName === 'condition') {
  11634. parser.parseLParen();
  11635. const regionArgs = [];
  11636. while (parser.getToken().isNot(_.Token.r_paren)) {
  11637. const arg = parser.parseOperand();
  11638. let type = null;
  11639. if (parser.parseOptionalColon()) {
  11640. type = parser.parseType();
  11641. }
  11642. regionArgs.push({ value: arg, type });
  11643. if (!parser.parseOptionalComma()) {
  11644. break;
  11645. }
  11646. }
  11647. parser.parseRParen();
  11648. parser.parseArrow();
  11649. parser.parseType();
  11650. const conditionRegion = { arguments: regionArgs };
  11651. parser.parseRegion(conditionRegion);
  11652. result.regions.push(conditionRegion);
  11653. continue;
  11654. }
  11655. if (parser.parseOptionalLParen()) {
  11656. let parenDepth = 1;
  11657. let paramValue = '';
  11658. while (parenDepth > 0 && parser.getToken().isNot(_.Token.eof)) {
  11659. if (parser.getToken().is(_.Token.l_paren)) {
  11660. parenDepth++;
  11661. paramValue += parser.getToken().getSpelling().str();
  11662. parser.consumeToken();
  11663. } else if (parser.getToken().is(_.Token.r_paren)) {
  11664. parenDepth--;
  11665. if (parenDepth > 0) {
  11666. paramValue += parser.getToken().getSpelling().str();
  11667. parser.consumeToken();
  11668. } else {
  11669. parser.parseRParen();
  11670. }
  11671. } else {
  11672. paramValue += parser.getToken().getSpelling().str();
  11673. parser.consumeToken();
  11674. }
  11675. }
  11676. result.addAttribute(paramName, paramValue);
  11677. parser.parseOptionalComma();
  11678. } else if (parser.parseOptionalEqual()) {
  11679. if (parser.getToken().is(_.Token.hash_identifier)) {
  11680. const value = parser.parseAttribute();
  11681. result.addAttribute(paramName, value.value);
  11682. } else if (parser.getToken().is(_.Token.string)) {
  11683. const value = parser.getToken().getSpelling().str();
  11684. parser.consumeToken(_.Token.string);
  11685. result.addAttribute(paramName, value);
  11686. } else {
  11687. const value = parser.getToken().getSpelling().str();
  11688. parser.consumeToken();
  11689. result.addAttribute(paramName, value);
  11690. }
  11691. if (!parser.parseOptionalComma()) {
  11692. break;
  11693. }
  11694. } else {
  11695. break;
  11696. }
  11697. }
  11698. if (parser.parseOptionalArrow()) {
  11699. const resultTypes = [];
  11700. const resultAttrs = [];
  11701. parser.parseFunctionResultList(resultTypes, resultAttrs);
  11702. }
  11703. if (parser.parseOptionalKeyword('attributes')) {
  11704. parser.parseAttributeDict(result.attributes);
  11705. }
  11706. if (parser.parseOptionalKeyword('count')) {
  11707. this.parseWorkgroupCountRegion(parser, result);
  11708. }
  11709. if (parser.getToken().is(_.Token.l_brace)) {
  11710. const region = result.addRegion();
  11711. parser.parseRegion(region);
  11712. }
  11713. if (parser.parseOptionalKeyword('attributes')) {
  11714. parser.parseAttributeDict(result.attributes);
  11715. }
  11716. if (parser.parseOptionalKeyword('count')) {
  11717. this.parseWorkgroupCountRegion(parser, result);
  11718. }
  11719. return true;
  11720. }
  11721. return super.parseOperation(parser, result);
  11722. }
  11723. parsePipelineLayoutAttr(parser) {
  11724. // HAL_PipelineLayoutAttr format: <constants = N, bindings = [...], flags = ...>
  11725. if (parser.getToken().is(_.Token.less)) {
  11726. return parser.parseAttribute();
  11727. }
  11728. return parser.parseOptionalAttribute();
  11729. }
  11730. parseExportConditionRegion(parser, result) {
  11731. parser.parseLParen();
  11732. const regionArgs = [];
  11733. while (parser.getToken().isNot(_.Token.r_paren)) {
  11734. const arg = parser.parseOperand();
  11735. let type = null;
  11736. if (parser.parseOptionalColon()) {
  11737. type = parser.parseType();
  11738. }
  11739. regionArgs.push({ value: arg, type });
  11740. if (!parser.parseOptionalComma()) {
  11741. break;
  11742. }
  11743. }
  11744. parser.parseRParen();
  11745. parser.parseArrow();
  11746. parser.parseType();
  11747. const region = { arguments: regionArgs };
  11748. parser.parseRegion(region);
  11749. result.regions.push(region);
  11750. }
  11751. parseTargetConditionObjects(parser, result) {
  11752. // #target if(...) { region } ordinal(N) = [objects], ...
  11753. do {
  11754. if (parser.getToken().is(_.Token.hash_identifier)) {
  11755. parser.parseAttribute();
  11756. }
  11757. if (parser.parseOptionalKeyword('if')) {
  11758. this.parseTargetConditionRegion(parser, result);
  11759. }
  11760. if (parser.parseOptionalKeyword('ordinal')) {
  11761. parser.parseLParen();
  11762. parser.consumeToken(_.Token.integer);
  11763. parser.parseRParen();
  11764. }
  11765. if (parser.parseOptionalEqual()) {
  11766. if (parser.getToken().is(_.Token.l_square)) {
  11767. parser.skip('[');
  11768. }
  11769. }
  11770. } while (parser.parseOptionalComma());
  11771. }
  11772. parseTargetConditionRegion(parser, result) {
  11773. parser.parseLParen();
  11774. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.eof)) {
  11775. parser.parseOperand();
  11776. if (parser.parseOptionalColon()) {
  11777. parser.parseType();
  11778. }
  11779. if (!parser.parseOptionalComma()) {
  11780. break;
  11781. }
  11782. }
  11783. parser.parseRParen();
  11784. if (parser.parseOptionalArrow()) {
  11785. parser.parseType();
  11786. }
  11787. if (parser.getToken().is(_.Token.l_brace)) {
  11788. const region = result.addRegion();
  11789. parser.parseRegion(region);
  11790. }
  11791. }
  11792. parseWorkgroupCountRegion(parser, result) {
  11793. // (args) -> (index, index, index) { region }
  11794. const region = { blocks: [] };
  11795. const block = { arguments: [], operations: [] };
  11796. if (parser.parseOptionalLParen()) {
  11797. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.eof)) {
  11798. const arg = parser.parseOperand();
  11799. if (parser.parseOptionalColon()) {
  11800. arg.type = parser.parseType();
  11801. }
  11802. block.arguments.push(arg);
  11803. if (!parser.parseOptionalComma()) {
  11804. break;
  11805. }
  11806. }
  11807. parser.parseRParen();
  11808. }
  11809. if (parser.parseOptionalArrow()) {
  11810. parser.parseLParen();
  11811. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.eof)) {
  11812. parser.parseType();
  11813. if (!parser.parseOptionalComma()) {
  11814. break;
  11815. }
  11816. }
  11817. parser.parseRParen();
  11818. }
  11819. region.blocks.push(block);
  11820. if (parser.getToken().is(_.Token.l_brace)) {
  11821. parser.parseRegion(region);
  11822. }
  11823. result.regions.push(region);
  11824. }
  11825. };
  11826. _.IREECodegenDialect = class extends _.Dialect {
  11827. constructor(operations) {
  11828. super(operations, 'iree_codegen');
  11829. }
  11830. inferResultTypes(op, vars) {
  11831. if (op.op === 'iree_codegen.inner_tiled') {
  11832. const outputsEntry = vars.get('outputs');
  11833. if (outputsEntry.types.length > 0) {
  11834. op.addTypes(outputsEntry.types);
  11835. return;
  11836. }
  11837. }
  11838. super.inferResultTypes(op, vars);
  11839. }
  11840. parseOperation(parser, result) {
  11841. if (result.op === 'iree_codegen.workgroup_count_hint') {
  11842. const staticSizes = [];
  11843. const unresolvedSizes = [];
  11844. parser.parseOptionalKeyword('sizes');
  11845. parser.parseLParen();
  11846. while (parser.getToken().isNot(_.Token.r_paren)) {
  11847. if (parser.getToken().is(_.Token.percent_identifier)) {
  11848. unresolvedSizes.push(parser.parseOperand());
  11849. staticSizes.push(-9223372036854775808);
  11850. } else if (parser.getToken().is(_.Token.integer)) {
  11851. const constValue = parser.getToken().getSpelling().str();
  11852. parser.consumeToken(_.Token.integer);
  11853. staticSizes.push(parseInt(constValue, 10));
  11854. }
  11855. if (!parser.parseOptionalComma()) {
  11856. break;
  11857. }
  11858. }
  11859. parser.parseRParen();
  11860. // Resolve operands with index type (sizes are typically index)
  11861. const indexType = new _.IndexType();
  11862. for (const unresolved of unresolvedSizes) {
  11863. parser.resolveOperand(unresolved, indexType, result.operands);
  11864. }
  11865. if (staticSizes.length > 0) {
  11866. result.addAttribute('static_sizes', staticSizes);
  11867. }
  11868. parser.parseOptionalAttrDict(result.attributes);
  11869. return true;
  11870. }
  11871. return super.parseOperation(parser, result);
  11872. }
  11873. };
  11874. _.HALLoaderDialect = class extends _.Dialect {
  11875. constructor(operations) {
  11876. super(operations, 'hal_loader');
  11877. this.registerCustomDirective('DispatchBindings', this.parseDispatchBindings.bind(this));
  11878. }
  11879. parseDispatchBindings(parser, result) {
  11880. const unresolvedBuffers = [];
  11881. const bufferTypes = [];
  11882. const unresolvedOffsets = [];
  11883. const unresolvedLengths = [];
  11884. do {
  11885. parser.parseLParen();
  11886. unresolvedBuffers.push(parser.parseOperand());
  11887. parser.parseColon();
  11888. bufferTypes.push(parser.parseType());
  11889. parser.parseRParen();
  11890. parser.parseLSquare();
  11891. unresolvedOffsets.push(parser.parseOperand());
  11892. parser.parseComma();
  11893. unresolvedLengths.push(parser.parseOperand());
  11894. parser.parseRSquare();
  11895. } while (parser.parseOptionalComma());
  11896. const indexType = new _.IndexType();
  11897. for (let i = 0; i < unresolvedBuffers.length; i++) {
  11898. parser.resolveOperand(unresolvedBuffers[i], bufferTypes[i], result.operands);
  11899. }
  11900. for (const unresolved of unresolvedOffsets) {
  11901. parser.resolveOperand(unresolved, indexType, result.operands);
  11902. }
  11903. for (const unresolved of unresolvedLengths) {
  11904. parser.resolveOperand(unresolved, indexType, result.operands);
  11905. }
  11906. }
  11907. };
  11908. _.UtilDialect = class extends _.IREEDialect {
  11909. constructor(operations) {
  11910. super(operations, 'util');
  11911. this.registerCustomDirective('OperandTypeList', this.parseOperandTypeList.bind(this));
  11912. this.registerCustomDirective('TiedFunctionResultList', this.parseTiedFunctionResultList.bind(this));
  11913. this.registerCustomDirective('TypeAlias', this.parseTypeAlias.bind(this));
  11914. this.registerCustomDirective('TypedValueList', this.parseTypedValueList.bind(this));
  11915. this.registerCustomDirective('RangeList', this.parseRangeList.bind(this));
  11916. this.registerCustomDirective('ListTypeGet', this.parseListTypeGet.bind(this));
  11917. this.registerCustomDirective('ListTypeSet', this.parseListTypeSet.bind(this));
  11918. this.registerCustomDirective('ValueTypeList', this.parseValueTypeList.bind(this));
  11919. this.simpleTypes = new Set(['buffer', 'list', 'object', 'ptr']);
  11920. }
  11921. parseTypeAlias(parser /*, op, args */) {
  11922. parser.parseType();
  11923. if (parser.parseOptionalKeyword('as')) {
  11924. parser.parseType();
  11925. }
  11926. }
  11927. parseTypedValueList(parser, op /*, args */) {
  11928. parser.parseLSquare();
  11929. if (parser.getToken().isNot(_.Token.r_square)) {
  11930. const unresolvedValues = [];
  11931. do {
  11932. unresolvedValues.push(parser.parseOperand());
  11933. } while (parser.parseOptionalComma());
  11934. for (const unresolved of unresolvedValues) {
  11935. parser.resolveOperand(unresolved, null, op.operands);
  11936. }
  11937. }
  11938. parser.parseRSquare();
  11939. }
  11940. parseType(parser, dialect) {
  11941. const typeName = parser.parseOptionalKeyword();
  11942. if (!typeName) {
  11943. return null;
  11944. }
  11945. if (this.simpleTypes.has(typeName)) {
  11946. if (typeName === 'list' && parser.parseOptionalLess()) {
  11947. let elementType = null;
  11948. if (parser.consumeIf(_.Token.question)) {
  11949. elementType = new _.util.VariantType();
  11950. } else {
  11951. elementType = parser.parseType();
  11952. }
  11953. parser.parseGreater();
  11954. return new _.util.ListType(elementType);
  11955. }
  11956. let type = `!${dialect}.${typeName}`;
  11957. if (parser.getToken().is(_.Token.less)) {
  11958. type += parser.skip('<');
  11959. }
  11960. return new _.Type(type);
  11961. }
  11962. return null;
  11963. }
  11964. parseOperandTypeList(parser, op /*, args */) {
  11965. parser.parseLParen();
  11966. if (parser.getToken().isNot(_.Token.r_paren)) {
  11967. let index = 0;
  11968. do {
  11969. const type = parser.parseType();
  11970. if (index < op.operands.length) {
  11971. op.operands[index].type = type;
  11972. }
  11973. index++;
  11974. } while (parser.parseOptionalComma());
  11975. }
  11976. parser.parseRParen();
  11977. }
  11978. parseTiedFunctionResultList(parser, op /*, args */) {
  11979. const parseTiedResultOrType = () => {
  11980. if (parser.getToken().is(_.Token.percent_identifier)) {
  11981. const tiedRef = parser.parseOperand();
  11982. let tiedType = null;
  11983. for (let i = 0; i < op.operands.length; i++) {
  11984. if (op.operands[i].value === tiedRef) {
  11985. tiedType = op.operands[i].type;
  11986. break;
  11987. }
  11988. }
  11989. if (parser.parseOptionalKeyword('as')) {
  11990. return parser.parseType();
  11991. }
  11992. if (tiedType) {
  11993. return tiedType;
  11994. }
  11995. return new _.Type('!util.unknown');
  11996. }
  11997. return parser.parseType();
  11998. };
  11999. if (parser.parseOptionalLParen()) {
  12000. let index = 0;
  12001. if (parser.getToken().isNot(_.Token.r_paren)) {
  12002. do {
  12003. const type = parseTiedResultOrType();
  12004. if (index < op.types.length) {
  12005. op.types[index] = type;
  12006. } else {
  12007. op.addTypes([type]);
  12008. }
  12009. index++;
  12010. } while (parser.parseOptionalComma());
  12011. }
  12012. parser.parseRParen();
  12013. } else {
  12014. let index = 0;
  12015. do {
  12016. const type = parseTiedResultOrType();
  12017. if (index < op.types.length) {
  12018. op.types[index] = type;
  12019. } else {
  12020. op.addTypes([type]);
  12021. }
  12022. index++;
  12023. } while (parser.parseOptionalComma());
  12024. }
  12025. }
  12026. parseOperation(parser, result) {
  12027. if (result.op === 'util.assume.int') {
  12028. return this.parseAssumeIntOp(parser, result);
  12029. }
  12030. if (result.op === 'util.initializer') {
  12031. if (parser.parseOptionalKeyword('attributes')) {
  12032. parser.parseAttributeDict(result.attributes);
  12033. }
  12034. if (parser.getToken().is(_.Token.l_brace)) {
  12035. const region = result.addRegion();
  12036. parser.parseRegion(region);
  12037. }
  12038. return true;
  12039. }
  12040. if (result.op === 'util.unreachable') {
  12041. result.compatibility = true;
  12042. if (parser.getToken().is(_.Token.string)) {
  12043. const message = parser.getToken().getSpelling().str();
  12044. parser.consumeToken(_.Token.string);
  12045. result.addAttribute('message', message);
  12046. }
  12047. if (parser.getToken().is(_.Token.l_brace)) {
  12048. parser.parseAttributeDict(result.attributes);
  12049. }
  12050. return true;
  12051. }
  12052. if (result.op === 'util.func') {
  12053. this.parseUtilFuncOp(parser, result);
  12054. return true;
  12055. }
  12056. if (result.op === 'util.unfoldable_constant') {
  12057. if (parser.getToken().is(_.Token.l_brace)) {
  12058. parser.parseAttributeDict(result.attributes);
  12059. }
  12060. const value = parser.parseAttribute();
  12061. result.addAttribute('value', value);
  12062. // Use type from attribute if present, otherwise parse explicit type
  12063. if (value && value.type) {
  12064. result.addTypes([value.type]);
  12065. } else if (parser.parseOptionalColon()) {
  12066. const type = parser.parseType();
  12067. result.addTypes([type]);
  12068. }
  12069. return true;
  12070. }
  12071. return super.parseOperation(parser, result);
  12072. }
  12073. parseUtilFuncOp(parser, result) {
  12074. parser.parseOptionalVisibilityKeyword(result.attributes);
  12075. parser.parseSymbolName('sym_name', result.attributes);
  12076. const argResult = parser.parseFunctionArgumentList(false);
  12077. const resultTypes = [];
  12078. const resultAttrs = [];
  12079. const tiedOperandIndices = [];
  12080. // Parse result list which may contain:
  12081. // - Regular type: tensor<...>
  12082. // - Tied reference: %arg1 (inherits type from argument)
  12083. // - Tied with type override: %arg2 as tensor<...>
  12084. const parseTiedResultOrType = () => {
  12085. if (parser.getToken().is(_.Token.percent_identifier)) {
  12086. const tiedRef = parser.parseOperand();
  12087. let tiedIndex = -1;
  12088. for (let i = 0; i < argResult.arguments.length; i++) {
  12089. if (argResult.arguments[i].value === tiedRef) {
  12090. tiedIndex = i;
  12091. break;
  12092. }
  12093. }
  12094. tiedOperandIndices.push(tiedIndex);
  12095. // Check for 'as type' override
  12096. if (parser.parseOptionalKeyword('as')) {
  12097. return parser.parseType();
  12098. }
  12099. if (tiedIndex >= 0 && argResult.arguments[tiedIndex].type) {
  12100. return argResult.arguments[tiedIndex].type;
  12101. }
  12102. return new _.Type('!util.unknown');
  12103. }
  12104. tiedOperandIndices.push(-1);
  12105. return parser.parseType();
  12106. };
  12107. if (parser.parseOptionalArrow()) {
  12108. if (parser.parseOptionalLParen()) {
  12109. if (parser.getToken().isNot(_.Token.r_paren)) {
  12110. do {
  12111. resultTypes.push(parseTiedResultOrType());
  12112. if (parser.getToken().is(_.Token.l_brace)) {
  12113. const attrList = new Map();
  12114. parser.parseAttributeDict(attrList);
  12115. resultAttrs.push(attrList);
  12116. } else {
  12117. resultAttrs.push(null);
  12118. }
  12119. } while (parser.parseOptionalComma());
  12120. }
  12121. parser.parseRParen();
  12122. } else {
  12123. do {
  12124. resultTypes.push(parseTiedResultOrType());
  12125. resultAttrs.push(null);
  12126. } while (parser.parseOptionalComma());
  12127. }
  12128. }
  12129. const argTypes = argResult.arguments.filter((a) => a.value !== '...').map((a) => a.type);
  12130. const type = new _.FunctionType(argTypes, resultTypes);
  12131. result.addAttribute('function_type', new _.TypeAttrOf(type));
  12132. if (tiedOperandIndices.some((i) => i >= 0)) {
  12133. result.addAttribute('tied_operands', tiedOperandIndices);
  12134. }
  12135. if (resultAttrs.some((a) => a !== null)) {
  12136. result.addAttribute('res_attrs', resultAttrs);
  12137. }
  12138. const argAttrs = argResult.arguments.filter((a) => a.value !== '...').map((a) => a.attrs || null);
  12139. if (argAttrs.some((a) => a !== null)) {
  12140. result.addAttribute('arg_attrs', argAttrs);
  12141. }
  12142. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  12143. if (parser.getToken().is(_.Token.l_brace)) {
  12144. const region = result.addRegion();
  12145. parser.parseRegion(region, argResult.arguments);
  12146. }
  12147. }
  12148. parseAssumeIntOp(parser, result) {
  12149. const allOperandAssumptions = [];
  12150. const unresolvedOperands = [];
  12151. do {
  12152. const operand = parser.parseOperand();
  12153. unresolvedOperands.push(operand);
  12154. const operandAssumptions = [];
  12155. if (parser.parseOptionalLSquare()) {
  12156. if (parser.getToken().isNot(_.Token.r_square)) {
  12157. do {
  12158. const assumption = this.parseIntAssumptionAttr(parser);
  12159. operandAssumptions.push(assumption);
  12160. } while (parser.parseOptionalComma());
  12161. }
  12162. parser.parseRSquare();
  12163. } else if (parser.getToken().is(_.Token.less)) {
  12164. const assumption = this.parseIntAssumptionAttr(parser);
  12165. operandAssumptions.push(assumption);
  12166. }
  12167. allOperandAssumptions.push(operandAssumptions);
  12168. } while (parser.parseOptionalComma());
  12169. parser.parseColon();
  12170. const parsedOperandTypes = [];
  12171. do {
  12172. const type = parser.parseType();
  12173. parsedOperandTypes.push(type);
  12174. } while (parser.parseOptionalComma());
  12175. parser.resolveOperands(unresolvedOperands, parsedOperandTypes, result.operands);
  12176. for (const type of parsedOperandTypes) {
  12177. result.addTypes([type || null]);
  12178. }
  12179. result.addAttribute('assumptions', allOperandAssumptions);
  12180. if (parser.getToken().is(_.Token.l_brace)) {
  12181. parser.parseAttributeDict(result.attributes);
  12182. }
  12183. return true;
  12184. }
  12185. parseIntAssumptionAttr(parser) {
  12186. parser.parseLess();
  12187. const assumption = {};
  12188. if (parser.getToken().isNot(_.Token.greater)) {
  12189. do {
  12190. const key = parser.getToken().getSpelling().str();
  12191. parser.consumeToken(_.Token.bare_identifier);
  12192. if (!parser.parseOptionalEqual()) {
  12193. throw new mlir.Error(`Expected '=' after ${key} ${parser.location()}`);
  12194. }
  12195. const value = parser.getToken().getSpelling().str();
  12196. parser.consumeToken(_.Token.integer);
  12197. assumption[key] = value;
  12198. } while (parser.parseOptionalComma());
  12199. }
  12200. parser.parseGreater();
  12201. return assumption;
  12202. }
  12203. parseRangeList(parser, op, offsetsAttr) {
  12204. const unresolvedOffsets = [];
  12205. const unresolvedLengths = [];
  12206. do {
  12207. parser.parseLSquare();
  12208. unresolvedOffsets.push(parser.parseOperand());
  12209. parser.parseKeyword('for');
  12210. unresolvedLengths.push(parser.parseOperand());
  12211. parser.parseRSquare();
  12212. } while (parser.parseOptionalComma());
  12213. const indexType = new _.IndexType();
  12214. for (const unresolved of unresolvedOffsets) {
  12215. parser.resolveOperand(unresolved, indexType, op.operands);
  12216. }
  12217. for (const unresolved of unresolvedLengths) {
  12218. parser.resolveOperand(unresolved, indexType, op.operands);
  12219. }
  12220. if (offsetsAttr) {
  12221. op.addAttribute(`${offsetsAttr}_count`, unresolvedOffsets.length);
  12222. }
  12223. }
  12224. parseListTypeGet(parser, op, listTypeArr, resultTypeArr) {
  12225. const listType = parser.parseType();
  12226. let elementType = null;
  12227. if (parser.parseOptionalArrow()) {
  12228. elementType = parser.parseType();
  12229. } else if (listType instanceof _.util.ListType) {
  12230. elementType = listType.elementType;
  12231. }
  12232. if (Array.isArray(listTypeArr) && listType) {
  12233. listTypeArr.push(listType);
  12234. }
  12235. if (Array.isArray(resultTypeArr) && elementType) {
  12236. resultTypeArr.push(elementType);
  12237. }
  12238. }
  12239. parseListTypeSet(parser, op, listTypeArr, valueTypeArr) {
  12240. const leadingType = parser.parseType();
  12241. let listType = null;
  12242. let elementType = null;
  12243. if (parser.parseOptionalArrow()) {
  12244. elementType = leadingType;
  12245. listType = parser.parseType();
  12246. } else if (leadingType instanceof _.util.ListType) {
  12247. listType = leadingType;
  12248. elementType = leadingType.elementType;
  12249. }
  12250. if (Array.isArray(listTypeArr) && listType) {
  12251. listTypeArr.push(listType);
  12252. }
  12253. if (Array.isArray(valueTypeArr) && elementType) {
  12254. valueTypeArr.push(elementType);
  12255. }
  12256. }
  12257. parseValueTypeList(parser, result) {
  12258. parser.parseLSquare();
  12259. if (parser.getToken().isNot(_.Token.r_square)) {
  12260. const unresolvedOperands = [];
  12261. const types = [];
  12262. do {
  12263. unresolvedOperands.push(parser.parseOperand());
  12264. parser.parseColon();
  12265. types.push(parser.parseType());
  12266. } while (parser.parseOptionalComma());
  12267. parser.resolveOperands(unresolvedOperands, types, result.operands);
  12268. }
  12269. parser.parseRSquare();
  12270. }
  12271. };
  12272. _.FlowDialect = class extends _.IREEDialect {
  12273. constructor(operations) {
  12274. super(operations, 'flow');
  12275. this.registerCustomDirective('DispatchWorkgroupBody', this.parseDispatchWorkgroupBody.bind(this));
  12276. this.registerCustomDirective('DispatchWorkgroupsCountRegion', this.parseDispatchWorkgroupsCountRegion.bind(this));
  12277. this.registerCustomDirective('ShapedFunctionType', this.parseShapedFunctionType.bind(this));
  12278. this.registerCustomDirective('ShapedOperandList', this.parseShapedOperandList.bind(this));
  12279. this.registerCustomDirective('ParameterReference', this.parseParameterReference.bind(this));
  12280. }
  12281. parseParameterReference(parser, op, scopeOperands, keyOperands) {
  12282. const firstOperand = parser.parseOperand();
  12283. if (parser.parseOptionalColon()) {
  12284. parser.parseColon();
  12285. const keyOperand = parser.parseOperand();
  12286. scopeOperands.push(firstOperand);
  12287. keyOperands.push(keyOperand);
  12288. } else {
  12289. keyOperands.push(firstOperand);
  12290. }
  12291. }
  12292. parseType(parser, dialect) {
  12293. const typeName = parser.parseOptionalKeyword();
  12294. if (!typeName) {
  12295. return null;
  12296. }
  12297. let type = `!${dialect}.${typeName}`;
  12298. if (typeName === 'channel') {
  12299. return new _.Type(type);
  12300. }
  12301. if (typeName === 'dispatch.tensor') {
  12302. if (parser.getToken().is(_.Token.less)) {
  12303. const content = parser.skip('<');
  12304. type += content;
  12305. }
  12306. return new _.Type(type);
  12307. }
  12308. return null;
  12309. }
  12310. parseOperation(parser, result) {
  12311. if (result.op === 'flow.ex.stream.fragment') {
  12312. return this.parseDispatchWorkgroupsOp(parser, result);
  12313. }
  12314. if (result.op === 'flow.dispatch.region') {
  12315. return this.parseDispatchRegionOp(parser, result);
  12316. }
  12317. if (result.op === 'flow.dispatch.tensor.load' || result.op === 'flow.dispatch.tensor.store') {
  12318. return this.parseTensorLoadStoreOp(parser, result);
  12319. }
  12320. // Handle operations with visibility + symbol that aren't in schema or need manual parsing
  12321. if (result.op === 'flow.dispatch.entry') {
  12322. this.parseSymbolVisibility(parser, result);
  12323. if (parser.getToken().is(_.Token.at_identifier)) {
  12324. parser.parseSymbolName('sym_name', result.attributes);
  12325. }
  12326. if (parser.parseOptionalKeyword('attributes')) {
  12327. parser.parseAttributeDict(result.attributes);
  12328. }
  12329. if (parser.getToken().is(_.Token.l_brace)) {
  12330. const region = result.addRegion();
  12331. parser.parseRegion(region);
  12332. }
  12333. return true;
  12334. }
  12335. if (result.op === 'flow.func') {
  12336. return this.parseFlowFuncOp(parser, result);
  12337. }
  12338. return super.parseOperation(parser, result);
  12339. }
  12340. parseFlowFuncOp(parser, result) {
  12341. parser.parseOptionalVisibilityKeyword(result.attributes);
  12342. parser.parseSymbolName('sym_name', result.attributes);
  12343. const argResult = parser.parseFunctionArgumentList();
  12344. const inputs = argResult.arguments.map((a) => a.type);
  12345. const results = [];
  12346. if (parser.parseOptionalArrow()) {
  12347. const hasParens = parser.parseOptionalLParen();
  12348. if (!hasParens || parser.getToken().isNot(_.Token.r_paren)) {
  12349. do {
  12350. if (parser.getToken().is(_.Token.percent_identifier)) {
  12351. parser.parseOperand();
  12352. if (parser.parseOptionalKeyword('as')) {
  12353. const resultType = parser.parseType();
  12354. results.push(resultType);
  12355. } else {
  12356. results.push(new _.Type('tied'));
  12357. }
  12358. } else {
  12359. const resultType = parser.parseType();
  12360. results.push(resultType);
  12361. }
  12362. if (parser.getToken().is(_.Token.l_brace)) {
  12363. parser.skip('{');
  12364. }
  12365. if (!hasParens) {
  12366. break;
  12367. }
  12368. } while (parser.parseOptionalComma());
  12369. }
  12370. if (hasParens) {
  12371. parser.parseRParen();
  12372. }
  12373. }
  12374. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  12375. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  12376. if (parser.getToken().is(_.Token.l_brace)) {
  12377. const region = result.addRegion();
  12378. parser.parseRegion(region);
  12379. }
  12380. return true;
  12381. }
  12382. parseDispatchRegionOp(parser, result) {
  12383. const workloadOperands = parser.parseOperandList('optionalSquare');
  12384. for (const workload of workloadOperands) {
  12385. parser.resolveOperand(workload, null, result.operands);
  12386. }
  12387. if (parser.parseOptionalArrow()) {
  12388. if (parser.parseOptionalLParen()) {
  12389. while (!parser.parseOptionalRParen()) {
  12390. const type = parser.parseType();
  12391. if (parser.parseOptionalLBrace()) {
  12392. while (!parser.parseOptionalRBrace()) {
  12393. const tied = parser.parseOperand();
  12394. parser.resolveOperand(tied, null, result.operands);
  12395. parser.parseOptionalComma();
  12396. }
  12397. }
  12398. result.types.push(type);
  12399. parser.parseOptionalComma();
  12400. }
  12401. }
  12402. }
  12403. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  12404. if (parser.getToken().is(_.Token.l_brace)) {
  12405. const region = result.addRegion();
  12406. parser.parseRegion(region);
  12407. }
  12408. this.parseDispatchWorkgroupsCountRegion(parser, result);
  12409. return true;
  12410. }
  12411. parseDispatchWorkgroupsOp(parser, result) {
  12412. if (parser.parseOptionalLSquare()) {
  12413. while (!parser.parseOptionalRSquare()) {
  12414. parser.consumeToken(); // read subscript value
  12415. parser.parseOptionalComma();
  12416. }
  12417. }
  12418. const unresolvedOperands = parser.parseOperandList('paren');
  12419. if (parser.parseOptionalColon()) {
  12420. if (parser.parseOptionalLParen()) {
  12421. const inputTypes = parser.parseTypeListNoParens();
  12422. parser.parseRParen();
  12423. parser.resolveOperands(unresolvedOperands, inputTypes, result.operands);
  12424. parser.parseArrow();
  12425. const resultTypes = parser.parseFunctionResultTypes();
  12426. result.addTypes(resultTypes);
  12427. } else {
  12428. const types = parser.parseTypeListNoParens();
  12429. parser.resolveOperands(unresolvedOperands, types, result.operands);
  12430. if (parser.parseOptionalArrow()) {
  12431. const resultTypes = parser.parseFunctionResultTypes();
  12432. result.addTypes(resultTypes);
  12433. }
  12434. }
  12435. } else if (parser.parseOptionalArrow()) {
  12436. const types = parser.parseFunctionResultTypes();
  12437. result.addTypes(types);
  12438. }
  12439. if (parser.parseOptionalKeyword('attributes')) {
  12440. parser.parseAttributeDict(result.attributes);
  12441. }
  12442. if (parser.parseOptionalEqual()) {
  12443. const args = [];
  12444. if (parser.parseOptionalLParen()) {
  12445. while (!parser.parseOptionalRParen()) {
  12446. const arg = parser.parseArgument(true, false);
  12447. args.push(arg);
  12448. parser.parseOptionalComma();
  12449. }
  12450. }
  12451. if (parser.parseOptionalArrow() || parser.parseOptionalKeyword('to')) {
  12452. parser.parseType();
  12453. }
  12454. const region = result.addRegion();
  12455. parser.parseRegion(region, args, /* enableNameShadowing */ true);
  12456. }
  12457. return true;
  12458. }
  12459. parseShapedFunctionType(parser, op, unresolvedArguments /*, otherArgs */) {
  12460. // unresolvedArguments is ref($arguments) - array of unresolved operands with .name and .number
  12461. const operandTypes = [];
  12462. if (parser.parseOptionalLParen()) {
  12463. let index = 0;
  12464. if (parser.getToken().isNot(_.Token.r_paren)) {
  12465. do {
  12466. const type = parser.parseType();
  12467. if (type) {
  12468. operandTypes.push(type);
  12469. const startIdx = Math.max(0, op.operands.length - (index + 1));
  12470. if (startIdx + index < op.operands.length && !op.operands[startIdx + index].type) {
  12471. op.operands[startIdx + index].type = type;
  12472. }
  12473. index++;
  12474. }
  12475. if (parser.parseOptionalLBrace()) {
  12476. while (!parser.parseOptionalRBrace()) {
  12477. parser.parseOperand();
  12478. parser.parseOptionalComma();
  12479. }
  12480. }
  12481. } while (parser.parseOptionalComma());
  12482. }
  12483. parser.parseRParen();
  12484. }
  12485. if (parser.parseOptionalArrow()) {
  12486. let index = 0;
  12487. const hasParens = parser.parseOptionalLParen();
  12488. if (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.l_brace) && parser.getToken().isNot(_.Token.kw_loc) && parser.getToken().isNot(_.Token.equal)) {
  12489. do {
  12490. if (parser.getToken().is(_.Token.percent_identifier)) {
  12491. const tiedResult = parser.parseOperand();
  12492. // Handle optional "as type" for tied results
  12493. if (parser.parseOptionalKeyword('as')) {
  12494. const type = parser.parseType();
  12495. if (type) {
  12496. if (index < op.types.length) {
  12497. op.types[index] = type;
  12498. } else {
  12499. op.addTypes([type]);
  12500. }
  12501. }
  12502. } else {
  12503. // Look up type from tied operand using unresolvedArguments
  12504. // unresolvedArguments contains UnresolvedOperand objects with .name and .number
  12505. const operands = unresolvedArguments || [];
  12506. const tiedOperandIndex = parser.findTiedOperand(tiedResult, operands);
  12507. if (tiedOperandIndex >= 0 && tiedOperandIndex < operandTypes.length) {
  12508. const type = operandTypes[tiedOperandIndex];
  12509. if (type) {
  12510. if (index < op.types.length) {
  12511. op.types[index] = type;
  12512. } else {
  12513. op.addTypes([type]);
  12514. }
  12515. }
  12516. }
  12517. }
  12518. index++;
  12519. } else {
  12520. const type = parser.parseType();
  12521. if (type) {
  12522. if (index < op.types.length) {
  12523. op.types[index] = type;
  12524. } else {
  12525. op.addTypes([type]);
  12526. }
  12527. index++;
  12528. }
  12529. }
  12530. if (parser.parseOptionalLBrace()) {
  12531. while (!parser.parseOptionalRBrace()) {
  12532. parser.parseOperand();
  12533. parser.parseOptionalComma();
  12534. }
  12535. }
  12536. if (!hasParens) {
  12537. break;
  12538. }
  12539. } while (parser.parseOptionalComma());
  12540. }
  12541. if (hasParens) {
  12542. parser.parseRParen();
  12543. }
  12544. }
  12545. }
  12546. parseTensorLoadStoreOp(parser, result) {
  12547. // or: store %26, %arg4, offsets = [...] : type -> type
  12548. const unresolvedOperands = [];
  12549. while (parser.getToken().is(_.Token.percent_identifier)) {
  12550. unresolvedOperands.push(parser.parseOperand());
  12551. if (!parser.parseOptionalComma()) {
  12552. break;
  12553. }
  12554. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  12555. break;
  12556. }
  12557. }
  12558. // Note: first parameter might not need comma-eating if we just broke from operand loop
  12559. let needComma = parser.getToken().isNot(_.Token.bare_identifier); // If we're not at _.Token.bare_identifier, we need to eat commas
  12560. while (needComma ? parser.parseOptionalComma() : true) {
  12561. needComma = true; // After first iteration, always need comma
  12562. if (parser.getToken().is(_.Token.bare_identifier)) {
  12563. const paramName = parser.getToken().getSpelling().str();
  12564. parser.consumeToken(_.Token.bare_identifier);
  12565. if (parser.parseOptionalEqual()) {
  12566. if (parser.getToken().is(_.Token.l_square)) {
  12567. parser.skip('[');
  12568. } else {
  12569. parser.consumeToken();
  12570. }
  12571. result.addAttribute(paramName, paramName);
  12572. }
  12573. } else {
  12574. break;
  12575. }
  12576. }
  12577. const types = parser.parseOptionalColonTypeList();
  12578. parser.resolveOperands(unresolvedOperands, types, result.operands);
  12579. // For tensor.load, there's a -> result type
  12580. // For tensor.store, the -> is followed by the output tensor type (not a result)
  12581. if (parser.parseOptionalArrow() || parser.parseOptionalKeyword('to')) {
  12582. const resultType = parser.parseType();
  12583. if (result.op === 'flow.dispatch.tensor.load' && resultType) {
  12584. result.addTypes([resultType]);
  12585. }
  12586. }
  12587. return true;
  12588. }
  12589. parseDispatchWorkgroupBody(parser, op /*, args */) {
  12590. parser.parseLParen();
  12591. const regionArgs = [];
  12592. if (parser.getToken().isNot(_.Token.r_paren)) {
  12593. do {
  12594. const arg = parser.parseOperand();
  12595. parser.parseColon();
  12596. const argType = parser.parseType();
  12597. regionArgs.push({ name: arg, type: argType });
  12598. } while (parser.parseOptionalComma());
  12599. }
  12600. parser.parseRParen();
  12601. const region = { blocks: [{ arguments: regionArgs, operations: [] }] };
  12602. parser.parseRegion(region);
  12603. op.regions.push(region);
  12604. }
  12605. parseDispatchWorkgroupsCountRegion(parser, op /*, args */) {
  12606. if (!parser.parseOptionalKeyword('count')) {
  12607. return;
  12608. }
  12609. parser.parseLParen();
  12610. const regionArgs = [];
  12611. if (parser.getToken().isNot(_.Token.r_paren)) {
  12612. do {
  12613. const arg = parser.parseOperand();
  12614. parser.parseColon();
  12615. const argType = parser.parseType();
  12616. regionArgs.push({ name: arg, type: argType });
  12617. } while (parser.parseOptionalComma());
  12618. }
  12619. parser.parseRParen();
  12620. parser.parseArrow();
  12621. if (parser.parseOptionalLParen()) {
  12622. parser.parseType();
  12623. parser.parseOptionalComma();
  12624. parser.parseType();
  12625. parser.parseOptionalComma();
  12626. parser.parseType();
  12627. parser.parseRParen();
  12628. } else {
  12629. parser.parseType();
  12630. parser.parseOptionalComma();
  12631. parser.parseType();
  12632. parser.parseOptionalComma();
  12633. parser.parseType();
  12634. }
  12635. const region = { blocks: [{ arguments: regionArgs, operations: [] }] };
  12636. parser.parseRegion(region);
  12637. op.regions.push(region);
  12638. }
  12639. parseShapedOperandList(parser, result) {
  12640. const unresolvedValues = [];
  12641. const valueTypes = [];
  12642. const unresolvedDims = [];
  12643. do {
  12644. unresolvedValues.push(parser.parseOperand());
  12645. parser.parseColon();
  12646. const valueType = parser.parseType();
  12647. valueTypes.push(valueType);
  12648. if (valueType) {
  12649. const typeStr = valueType.toString();
  12650. const dynamicDimCount = (typeStr.match(/\?/g) || []).length;
  12651. if (dynamicDimCount > 0 && parser.parseOptionalLBrace()) {
  12652. for (let i = 0; i < dynamicDimCount; i++) {
  12653. if (i > 0) {
  12654. parser.parseOptionalComma();
  12655. }
  12656. unresolvedDims.push(parser.parseOperand());
  12657. }
  12658. parser.parseRBrace();
  12659. }
  12660. }
  12661. } while (parser.parseOptionalComma());
  12662. for (let i = 0; i < unresolvedValues.length; i++) {
  12663. parser.resolveOperand(unresolvedValues[i], valueTypes[i], result.operands);
  12664. }
  12665. const indexType = new _.IndexType();
  12666. for (const unresolved of unresolvedDims) {
  12667. parser.resolveOperand(unresolved, indexType, result.operands);
  12668. }
  12669. }
  12670. };
  12671. _.StreamDialect = class extends _.IREEDialect {
  12672. constructor(operations, name = 'stream') {
  12673. super(operations, name);
  12674. this.registerCustomDirective('DispatchOperands', this.parseDispatchOperands.bind(this));
  12675. this.registerCustomDirective('DispatchResources', this.parseDispatchResources.bind(this));
  12676. this.registerCustomDirective('ExplicitResourceRegion', this.parseExplicitResourceRegion.bind(this));
  12677. this.registerCustomDirective('ShapedTypeList', this.parseShapedTypeList.bind(this));
  12678. this.registerCustomDirective('ResourceRegion', this.parseResourceRegion.bind(this));
  12679. this.registerCustomDirective('ParameterLoadOperations', this.parseParameterLoadOperations.bind(this));
  12680. this.registerCustomDirective('EncodedResourceOperands', this.parseEncodedResourceOperands.bind(this));
  12681. this.registerCustomDirective('DispatchEntryPoints', this.parseDispatchEntryPoints.bind(this));
  12682. this.registerCustomDirective('ShapedTiedResult', this.parseShapedTiedResult.bind(this));
  12683. this.registerCustomDirective('EncodedShapedFunctionType', this.parseEncodedShapedFunctionType.bind(this));
  12684. this.registerCustomDirective('CollectiveParam', this.parseCollectiveParam.bind(this));
  12685. this.registerCustomDirective('PackSliceRanges', this.parsePackSliceRanges.bind(this));
  12686. this.registerCustomDirective('WorkgroupCountRegion', this.parseWorkgroupCountRegion.bind(this));
  12687. this.registerCustomDirective('DispatchFunctionSignature', this.parseDispatchFunctionSignature.bind(this));
  12688. this.registerCustomDirective('ShapedFunctionSignature', this.parseShapedFunctionSignature.bind(this));
  12689. this.registerCustomDirective('ConstantValueList', this.parseConstantValueList.bind(this));
  12690. this.registerCustomDirective('CmdCallOperands', this.parseCmdCallOperands.bind(this));
  12691. this.registerCustomDirective('ParameterReference', this.parseParameterReference.bind(this));
  12692. this.registerCustomDirective('ParameterGatherOperations', this.parseParameterGatherOperations.bind(this));
  12693. this.registerCustomDirective('ParameterScatterOperations', this.parseParameterScatterOperations.bind(this));
  12694. this.registerCustomDirective('SymbolAlias', this.parseSymbolAlias.bind(this));
  12695. }
  12696. parseDispatchResources(parser, op /*, args */) {
  12697. do {
  12698. const accessMode = parser.getToken().getSpelling().str();
  12699. parser.consumeToken(_.Token.bare_identifier);
  12700. const unresolvedResource = parser.parseOperand();
  12701. parser.parseLSquare();
  12702. const unresolvedOffset = parser.parseOperand();
  12703. parser.parseKeyword('for');
  12704. const unresolvedLength = parser.parseOperand();
  12705. parser.parseRSquare();
  12706. parser.parseColon();
  12707. const resourceType = parser.parseType();
  12708. if (parser.getToken().is(_.Token.l_brace)) {
  12709. parser.skip('{');
  12710. }
  12711. op.addAttribute('resource_access', accessMode);
  12712. parser.resolveOperand(unresolvedResource, resourceType, op.operands);
  12713. const indexType = new _.IndexType();
  12714. parser.resolveOperand(unresolvedOffset, indexType, op.operands);
  12715. parser.resolveOperand(unresolvedLength, indexType, op.operands);
  12716. } while (parser.parseOptionalComma());
  12717. }
  12718. parseShapedTypeList(parser, op, ...args) {
  12719. // 2-arg: custom<ShapedTypeList>(type($operands), $sizes)
  12720. // 3-arg: custom<ShapedTypeList>(type($operands), type($results), $sizes)
  12721. let operandTypes = null;
  12722. let resultTypes = null;
  12723. let sizeOperands = null;
  12724. if (args.length === 2) {
  12725. [operandTypes, sizeOperands] = args;
  12726. } else if (args.length >= 3) {
  12727. [operandTypes, resultTypes, sizeOperands] = args;
  12728. } else {
  12729. operandTypes = args[0] || null;
  12730. }
  12731. const indexType = new _.IndexType();
  12732. do {
  12733. const type = parser.parseType();
  12734. if (operandTypes) {
  12735. operandTypes.push(type);
  12736. }
  12737. if (resultTypes) {
  12738. resultTypes.push(type);
  12739. }
  12740. if (parser.parseOptionalLBrace()) {
  12741. do {
  12742. if (parser.getToken().is(_.Token.percent_identifier)) {
  12743. const sizeOperand = parser.parseOperand();
  12744. if (sizeOperands) {
  12745. sizeOperands.push(sizeOperand);
  12746. }
  12747. parser.resolveOperand(sizeOperand, indexType, op.operands);
  12748. }
  12749. } while (parser.parseOptionalComma());
  12750. parser.parseRBrace();
  12751. }
  12752. } while (parser.parseOptionalComma());
  12753. }
  12754. parseExplicitResourceRegion(parser, op /*, args */) {
  12755. parser.parseLParen();
  12756. const regionArgs = [];
  12757. const unresolvedOperands = [];
  12758. const operandTypes = [];
  12759. const unresolvedSizes = [];
  12760. if (parser.getToken().isNot(_.Token.r_paren)) {
  12761. do {
  12762. if (parser.getToken().is(_.Token.percent_identifier)) {
  12763. unresolvedOperands.push(parser.parseOperand());
  12764. }
  12765. parser.parseKeyword('as');
  12766. const arg = parser.parseOperand();
  12767. parser.parseColon();
  12768. const argType = parser.parseType();
  12769. operandTypes.push(argType);
  12770. regionArgs.push({ name: arg, type: argType });
  12771. if (parser.parseOptionalLBrace()) {
  12772. if (parser.getToken().is(_.Token.percent_identifier)) {
  12773. unresolvedSizes.push(parser.parseOperand());
  12774. }
  12775. parser.parseRBrace();
  12776. }
  12777. } while (parser.parseOptionalComma());
  12778. }
  12779. parser.parseRParen();
  12780. for (let i = 0; i < unresolvedOperands.length; i++) {
  12781. parser.resolveOperand(unresolvedOperands[i], operandTypes[i] || null, op.operands);
  12782. }
  12783. const indexType = new _.IndexType();
  12784. for (const unresolved of unresolvedSizes) {
  12785. parser.resolveOperand(unresolved, indexType, op.operands);
  12786. }
  12787. const region = { blocks: [{ arguments: regionArgs, operations: [] }] };
  12788. parser.parseRegion(region);
  12789. op.regions.push(region);
  12790. }
  12791. parseResourceRegion(parser, op /*, args */) {
  12792. const regionArgs = [];
  12793. const unresolvedOperands = [];
  12794. const operandTypes = [];
  12795. const unresolvedSizes = [];
  12796. const indexType = new _.IndexType();
  12797. parser.parseLParen();
  12798. if (parser.getToken().isNot(_.Token.r_paren)) {
  12799. do {
  12800. const operand = parser.parseOperand();
  12801. unresolvedOperands.push(operand);
  12802. parser.parseKeyword('as');
  12803. const arg = parser.parseOperand();
  12804. parser.parseColon();
  12805. const argType = parser.parseType();
  12806. operandTypes.push(argType);
  12807. regionArgs.push({ name: arg, type: argType });
  12808. if (parser.parseOptionalLBrace()) {
  12809. if (parser.getToken().is(_.Token.percent_identifier)) {
  12810. unresolvedSizes.push(parser.parseOperand());
  12811. }
  12812. parser.parseRBrace();
  12813. }
  12814. } while (parser.parseOptionalComma());
  12815. }
  12816. parser.parseRParen();
  12817. for (let i = 0; i < unresolvedOperands.length; i++) {
  12818. parser.resolveOperand(unresolvedOperands[i], operandTypes[i], op.operands);
  12819. }
  12820. for (const unresolved of unresolvedSizes) {
  12821. parser.resolveOperand(unresolved, indexType, op.operands);
  12822. }
  12823. const resultSizes = [];
  12824. const parseResultTypeOrTied = () => {
  12825. if (parser.getToken().is(_.Token.percent_identifier)) {
  12826. parser.parseOperand();
  12827. if (parser.parseOptionalKeyword('as')) {
  12828. const resultType = parser.parseType();
  12829. op.addTypes([resultType]);
  12830. } else {
  12831. op.addTypes([new _.Type('tied')]);
  12832. }
  12833. } else {
  12834. const resultType = parser.parseType();
  12835. op.addTypes([resultType]);
  12836. }
  12837. if (parser.parseOptionalLBrace()) {
  12838. if (parser.getToken().is(_.Token.percent_identifier)) {
  12839. resultSizes.push(parser.parseOperand());
  12840. }
  12841. parser.parseRBrace();
  12842. }
  12843. };
  12844. if (parser.parseOptionalArrow()) {
  12845. if (parser.parseOptionalLParen()) {
  12846. if (parser.getToken().isNot(_.Token.r_paren)) {
  12847. do {
  12848. parseResultTypeOrTied();
  12849. } while (parser.parseOptionalComma());
  12850. }
  12851. parser.parseRParen();
  12852. } else {
  12853. parseResultTypeOrTied();
  12854. }
  12855. }
  12856. for (const unresolved of resultSizes) {
  12857. parser.resolveOperand(unresolved, indexType, op.operands);
  12858. }
  12859. if (parser.getToken().is(_.Token.l_brace)) {
  12860. const region = { blocks: [{ arguments: regionArgs, operations: [] }] };
  12861. parser.parseRegion(region);
  12862. op.regions.push(region);
  12863. }
  12864. }
  12865. parseParameterLoadOperations(parser, op, sourceScopeOps, sourceKeysOps, sourceOffsetsOps, resultTypes, resultSizesOps) {
  12866. do {
  12867. const firstOperand = parser.parseOperand();
  12868. let key = firstOperand;
  12869. if (parser.parseOptionalColon()) {
  12870. sourceScopeOps.push(firstOperand);
  12871. parser.parseColon();
  12872. key = parser.parseOperand();
  12873. }
  12874. sourceKeysOps.push(key);
  12875. parser.parseLSquare();
  12876. sourceOffsetsOps.push(parser.parseOperand());
  12877. parser.parseRSquare();
  12878. parser.parseColon();
  12879. const resultType = parser.parseType();
  12880. op.addTypes([resultType]);
  12881. if (parser.parseOptionalLBrace()) {
  12882. resultSizesOps.push(parser.parseOperand());
  12883. parser.parseRBrace();
  12884. }
  12885. } while (parser.parseOptionalComma());
  12886. }
  12887. parseEncodedResourceOperands(parser /*, op, args */) {
  12888. do {
  12889. parser.parseOperand();
  12890. parser.parseColon();
  12891. parser.parseType();
  12892. parser.skip('{');
  12893. parser.parseKeyword('in');
  12894. parser.parseType();
  12895. parser.skip('{');
  12896. } while (parser.parseOptionalComma());
  12897. }
  12898. parseDispatchEntryPoints(parser, op /*, args */) {
  12899. if (parser.parseOptionalLBrace()) {
  12900. do {
  12901. const symbol = parser.getToken().getSpelling().str();
  12902. parser.consumeToken(_.Token.at_identifier);
  12903. op.addAttribute('entry_point', symbol);
  12904. } while (parser.parseOptionalComma());
  12905. parser.parseRBrace();
  12906. } else {
  12907. const symbol = parser.getToken().getSpelling().str();
  12908. parser.consumeToken(_.Token.at_identifier);
  12909. op.addAttribute('entry_point', symbol);
  12910. }
  12911. }
  12912. parseShapedTiedResult(parser, op /*, args */) {
  12913. if (parser.getToken().is(_.Token.percent_identifier)) {
  12914. parser.parseOperand(); // tiedOperand - parsed but not stored in OperationState
  12915. parser.parseKeyword('as');
  12916. }
  12917. const type = parser.parseType();
  12918. op.types.push(type);
  12919. if (parser.parseOptionalLBrace()) {
  12920. if (parser.getToken().is(_.Token.percent_identifier)) {
  12921. const unresolvedSize = parser.parseOperand();
  12922. const indexType = new _.IndexType();
  12923. parser.resolveOperand(unresolvedSize, indexType, op.operands);
  12924. }
  12925. parser.parseRBrace();
  12926. }
  12927. }
  12928. parseEncodedShapedTypeList(parser, types) {
  12929. do {
  12930. const type0 = parser.parseType();
  12931. parser.skip('{');
  12932. if (parser.parseOptionalKeyword('in')) {
  12933. const type1 = parser.parseType();
  12934. parser.skip('{');
  12935. types.push(type1);
  12936. } else {
  12937. types.push(type0);
  12938. }
  12939. } while (parser.parseOptionalComma());
  12940. }
  12941. parseEncodedShapedResultList(parser, operands, operandTypes, resultTypes) {
  12942. do {
  12943. let type0 = null;
  12944. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  12945. type0 = parser.parseType();
  12946. parser.skip('{');
  12947. }
  12948. if (!parser.parseOptionalKeyword('in')) {
  12949. if (type0) {
  12950. resultTypes.push(type0);
  12951. }
  12952. continue;
  12953. }
  12954. let resultType = null;
  12955. if (parser.getToken().is(_.Token.percent_identifier)) {
  12956. const tiedResult = parser.parseOperand();
  12957. const tiedOperandIndex = parser.findTiedOperand(tiedResult, operands);
  12958. if (parser.parseOptionalKeyword('as')) {
  12959. resultType = parser.parseType();
  12960. } else if (tiedOperandIndex >= 0 && operandTypes[tiedOperandIndex]) {
  12961. resultType = operandTypes[tiedOperandIndex];
  12962. }
  12963. } else {
  12964. resultType = parser.parseType();
  12965. }
  12966. parser.skip('{');
  12967. if (resultType) {
  12968. resultTypes.push(resultType);
  12969. }
  12970. } while (parser.parseOptionalComma());
  12971. }
  12972. parseEncodedShapedFunctionType(parser, op, operandsRef, operandTypes /* , ... */) {
  12973. parser.parseLParen();
  12974. if (parser.getToken().isNot(_.Token.r_paren)) {
  12975. this.parseEncodedShapedTypeList(parser, operandTypes);
  12976. }
  12977. parser.parseRParen();
  12978. parser.parseArrow();
  12979. if (parser.parseOptionalLParen()) {
  12980. if (parser.getToken().isNot(_.Token.r_paren)) {
  12981. this.parseEncodedShapedResultList(parser, operandsRef, operandTypes, op.types);
  12982. }
  12983. parser.parseRParen();
  12984. } else {
  12985. this.parseEncodedShapedResultList(parser, operandsRef, operandTypes, op.types);
  12986. }
  12987. }
  12988. parseCollectiveParam(parser, op /*, args */) {
  12989. for (const keyword of ['source', 'target', 'source_target_pair']) {
  12990. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === keyword) {
  12991. parser.consumeToken(_.Token.bare_identifier);
  12992. parser.parseLParen();
  12993. const unresolvedParam = parser.parseOperand();
  12994. parser.resolveOperand(unresolvedParam, null, op.operands);
  12995. parser.parseRParen();
  12996. return;
  12997. }
  12998. }
  12999. }
  13000. parsePackSliceRanges(parser, op, lifetimeIntervalsName, dynamicSliceSizesOperands, packedOffsetsTypes) {
  13001. const indexType = new _.IndexType();
  13002. while (parser.parseOptionalLSquare()) {
  13003. parser.parseAttribute();
  13004. parser.parseComma();
  13005. parser.parseAttribute();
  13006. parser.parseRSquare();
  13007. parser.parseEqual();
  13008. const unresolvedOperand = parser.parseOperand();
  13009. parser.resolveOperand(unresolvedOperand, indexType, op.operands);
  13010. packedOffsetsTypes.push(indexType);
  13011. if (!parser.parseOptionalComma()) {
  13012. break;
  13013. }
  13014. }
  13015. }
  13016. parseWorkgroupCountRegion(parser, op /*, args */) {
  13017. if (!parser.parseOptionalKeyword('workgroups')) {
  13018. return;
  13019. }
  13020. const region = { blocks: [] };
  13021. const block = { arguments: [], operations: [] };
  13022. if (parser.parseOptionalLParen()) {
  13023. while (parser.getToken().isNot(_.Token.r_paren)) {
  13024. const arg = parser.parseOperand();
  13025. if (parser.parseOptionalColon()) {
  13026. arg.type = parser.parseType();
  13027. }
  13028. block.arguments.push(arg);
  13029. if (!parser.parseOptionalComma()) {
  13030. break;
  13031. }
  13032. }
  13033. parser.parseRParen();
  13034. }
  13035. if (parser.parseOptionalArrow()) {
  13036. parser.parseLParen();
  13037. while (parser.getToken().isNot(_.Token.r_paren)) {
  13038. parser.parseType();
  13039. if (!parser.parseOptionalComma()) {
  13040. break;
  13041. }
  13042. }
  13043. parser.parseRParen();
  13044. }
  13045. region.blocks.push(block);
  13046. if (parser.getToken().is(_.Token.l_brace)) {
  13047. parser.parseRegion(region);
  13048. }
  13049. op.regions.push(region);
  13050. }
  13051. parseDispatchFunctionSignature(parser, op /*, args */) {
  13052. const inputs = [];
  13053. const results = [];
  13054. parser.parseLParen();
  13055. if (parser.getToken().isNot(_.Token.r_paren)) {
  13056. do {
  13057. parser.parseOperand();
  13058. // skip('[', ']') already handles checking for '[' presence
  13059. parser.skip('[');
  13060. parser.parseColon();
  13061. const type = parser.parseType();
  13062. inputs.push(type);
  13063. parser.skip('{');
  13064. } while (parser.parseOptionalComma());
  13065. }
  13066. parser.parseRParen();
  13067. const parseResultTypeOrTied = () => {
  13068. if (parser.getToken().is(_.Token.percent_identifier)) {
  13069. parser.parseOperand();
  13070. if (parser.parseOptionalKeyword('as')) {
  13071. return parser.parseType();
  13072. }
  13073. return new _.Type('tied');
  13074. }
  13075. return parser.parseType();
  13076. };
  13077. if (parser.parseOptionalArrow()) {
  13078. if (parser.parseOptionalLParen()) {
  13079. if (parser.getToken().isNot(_.Token.r_paren)) {
  13080. do {
  13081. results.push(parseResultTypeOrTied());
  13082. parser.skip('{');
  13083. } while (parser.parseOptionalComma());
  13084. }
  13085. parser.parseRParen();
  13086. } else {
  13087. results.push(parseResultTypeOrTied());
  13088. parser.skip('{');
  13089. }
  13090. }
  13091. op.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  13092. }
  13093. parseShapedFunctionSignature(parser, op /*, args */) {
  13094. this.parseDispatchFunctionSignature(parser, op);
  13095. }
  13096. parseConstantValueList(parser, op /*, args */) {
  13097. do {
  13098. const resultType = parser.parseType();
  13099. op.addTypes([resultType]);
  13100. if (parser.parseOptionalLBrace()) {
  13101. // Size is an SSA value like %c4, not an attribute
  13102. if (parser.getToken().is(_.Token.percent_identifier)) {
  13103. const unresolved = parser.parseOperand();
  13104. parser.resolveOperand(unresolved, null, op.operands);
  13105. } else {
  13106. const size = parser.parseAttribute();
  13107. if (size) {
  13108. // If it's an integer literal, create operand directly
  13109. op.operands.push(new _.Value(null, size));
  13110. }
  13111. }
  13112. parser.parseRBrace();
  13113. }
  13114. parser.parseEqual();
  13115. parser.parseAttribute();
  13116. if (parser.parseOptionalColon()) {
  13117. parser.parseType();
  13118. }
  13119. } while (parser.parseOptionalComma());
  13120. }
  13121. parseCmdCallOperands(parser, op /*, args */) {
  13122. parser.parseLParen();
  13123. if (parser.getToken().isNot(_.Token.r_paren)) {
  13124. const indexType = new _.IndexType();
  13125. do {
  13126. // Check for access mode keyword (ro, rw, wo)
  13127. const accessMode = parser.parseOptionalKeyword('ro') || parser.parseOptionalKeyword('rw') || parser.parseOptionalKeyword('wo');
  13128. if (accessMode) {
  13129. // Resource operand with offset/length: access operand[offset for length]
  13130. const unresolvedResource = parser.parseOperand();
  13131. parser.parseLSquare();
  13132. const unresolvedOffset = parser.parseOperand();
  13133. parser.parseKeyword('for');
  13134. const unresolvedLength = parser.parseOperand();
  13135. parser.parseRSquare();
  13136. op.addAttribute('resource_access', accessMode);
  13137. parser.resolveOperand(unresolvedResource, null, op.operands);
  13138. parser.resolveOperand(unresolvedOffset, indexType, op.operands);
  13139. parser.resolveOperand(unresolvedLength, indexType, op.operands);
  13140. } else {
  13141. // Primitive/custom operand
  13142. const unresolvedOperand = parser.parseOperand();
  13143. parser.resolveOperand(unresolvedOperand, null, op.operands);
  13144. }
  13145. } while (parser.parseOptionalComma());
  13146. }
  13147. parser.parseRParen();
  13148. }
  13149. parseParameterReference(parser, op, scopeOperands, keyOperands) {
  13150. const firstOperand = parser.parseOperand();
  13151. if (parser.parseOptionalColon()) {
  13152. parser.parseColon();
  13153. const keyOperand = parser.parseOperand();
  13154. if (scopeOperands) {
  13155. scopeOperands.push(firstOperand);
  13156. }
  13157. if (keyOperands) {
  13158. keyOperands.push(keyOperand);
  13159. }
  13160. } else if (keyOperands) {
  13161. keyOperands.push(firstOperand);
  13162. }
  13163. }
  13164. parseParameterGatherOperations(parser /*, op, args */) {
  13165. do {
  13166. // %scope::%key[offset] -> %target[offset for length] : type{size}
  13167. this.parseParameterReference(parser);
  13168. if (parser.parseOptionalLSquare()) {
  13169. parser.parseAttribute();
  13170. parser.parseRSquare();
  13171. }
  13172. parser.parseArrow();
  13173. parser.parseOperand();
  13174. if (parser.parseOptionalLSquare()) {
  13175. parser.parseAttribute();
  13176. parser.parseKeyword('for');
  13177. parser.parseAttribute();
  13178. parser.parseRSquare();
  13179. }
  13180. parser.parseColon();
  13181. parser.parseType();
  13182. if (parser.getToken().is(_.Token.l_brace)) {
  13183. parser.skip('{');
  13184. }
  13185. } while (parser.parseOptionalComma());
  13186. }
  13187. parseParameterScatterOperations(parser /*, op, args */) {
  13188. do {
  13189. // %source[offset for length] : type{size} -> %scope::%key[offset]
  13190. parser.parseOperand();
  13191. if (parser.parseOptionalLSquare()) {
  13192. parser.parseAttribute();
  13193. parser.parseKeyword('for');
  13194. parser.parseAttribute();
  13195. parser.parseRSquare();
  13196. }
  13197. parser.parseColon();
  13198. parser.parseType();
  13199. if (parser.getToken().is(_.Token.l_brace)) {
  13200. parser.skip('{');
  13201. }
  13202. parser.parseArrow();
  13203. this.parseParameterReference(parser);
  13204. if (parser.parseOptionalLSquare()) {
  13205. parser.parseAttribute();
  13206. parser.parseRSquare();
  13207. }
  13208. } while (parser.parseOptionalComma());
  13209. }
  13210. parseSymbolAlias(parser, op /*, args */) {
  13211. parser.parseSymbolName('sym_name', op.attributes);
  13212. if (parser.parseOptionalEqual()) {
  13213. const ref = parser.getToken().getSpelling().str();
  13214. parser.consumeToken(_.Token.at_identifier);
  13215. op.addAttribute('function_ref', ref);
  13216. }
  13217. }
  13218. parseType(parser, dialect) {
  13219. const typeName = parser.parseOptionalKeyword();
  13220. if (!typeName) {
  13221. return null;
  13222. }
  13223. let type = `!${dialect}.${typeName}`;
  13224. const simpleTypes = ['binding', 'channel', 'timepoint', 'file'];
  13225. if (simpleTypes.includes(typeName)) {
  13226. return new _.Type(type);
  13227. }
  13228. if (typeName === 'resource') {
  13229. if (parser.getToken().is(_.Token.less)) {
  13230. const content = parser.skip('<');
  13231. type += content;
  13232. }
  13233. return new _.Type(type);
  13234. }
  13235. // Handle test.fence type (Stream_TestFence in StreamTypes.td)
  13236. if (typeName === 'test') {
  13237. if (parser.consumeIf('.')) {
  13238. const subtype = parser.parseOptionalKeyword();
  13239. if (subtype === 'fence') {
  13240. return new _.Type(`!${dialect}.test.fence`);
  13241. }
  13242. // Handle unknown test.X subtypes generically
  13243. return new _.Type(`!${dialect}.test.${subtype}`);
  13244. }
  13245. // Just "test" without subtype - return as is
  13246. return new _.Type(type);
  13247. }
  13248. // Fallback for unknown stream types - parse generically like base Dialect
  13249. if (parser.getToken().is(_.Token.less)) {
  13250. type += parser.skip('<');
  13251. }
  13252. return new _.Type(type);
  13253. }
  13254. parseDispatchOperands(parser, op, resourceOperands /* offsets, ends, lengths */) {
  13255. // args are: [$resource_operands, $resource_operand_offsets, $resource_operand_ends, $resource_operand_lengths]
  13256. // resourceOperands is passed by ref so ShapedFunctionType can use it for tied operand lookup
  13257. parser.parseLParen();
  13258. if (parser.getToken().is(_.Token.r_paren)) {
  13259. parser.parseRParen();
  13260. return;
  13261. }
  13262. const unresolvedOperands = [];
  13263. do {
  13264. const operand = parser.parseOperand();
  13265. unresolvedOperands.push(operand);
  13266. if (Array.isArray(resourceOperands)) {
  13267. resourceOperands.push(operand);
  13268. }
  13269. if (parser.parseOptionalLSquare()) {
  13270. unresolvedOperands.push(parser.parseOperand()); // offset
  13271. parser.parseKeyword('to');
  13272. unresolvedOperands.push(parser.parseOperand()); // end
  13273. parser.parseKeyword('for');
  13274. unresolvedOperands.push(parser.parseOperand()); // length
  13275. parser.parseRSquare();
  13276. }
  13277. } while (parser.parseOptionalComma());
  13278. parser.parseRParen();
  13279. for (const unresolved of unresolvedOperands) {
  13280. parser.resolveOperand(unresolved, null, op.operands);
  13281. }
  13282. }
  13283. };
  13284. _.IOParametersDialect = class extends _.StreamDialect {
  13285. constructor(operations) {
  13286. super(operations, 'io_parameters');
  13287. }
  13288. };
  13289. _.PCFDialect = class extends _.Dialect {
  13290. constructor(operations) {
  13291. super(operations, 'pcf');
  13292. this.registerCustomDirective('ParallelExecutionBody', this.parseParallelExecutionBody.bind(this));
  13293. this.registerCustomDirective('InferNumIndexArgs', this.parseInferNumIndexArgs.bind(this));
  13294. }
  13295. parseInferNumIndexArgs() {
  13296. }
  13297. parseParallelExecutionBody(parser, result) {
  13298. const inits = [];
  13299. const dynamicSizes = [];
  13300. const resultTypes = [];
  13301. const isTied = [];
  13302. const regionRefArgs = [];
  13303. const indexArgs = [];
  13304. if (parser.parseOptionalArrow()) {
  13305. parser.parseLParen();
  13306. while (parser.getToken().isNot(_.Token.r_paren)) {
  13307. const arg = parser.parseOperand();
  13308. parser.parseColon();
  13309. const argType = parser.parseType();
  13310. result.addAttribute('num_leading_args', (result.attributes.get('num_leading_args') || 0) + 1);
  13311. regionRefArgs.push({ value: arg, type: argType });
  13312. if (!parser.parseOptionalComma()) {
  13313. break;
  13314. }
  13315. }
  13316. parser.parseRParen();
  13317. }
  13318. parser.parseKeyword('execute');
  13319. if (parser.parseOptionalLParen()) {
  13320. while (parser.getToken().isNot(_.Token.r_paren)) {
  13321. const refArg = parser.parseOperand();
  13322. regionRefArgs.push({ value: refArg });
  13323. if (parser.parseOptionalEqual()) {
  13324. const initOperand = parser.parseOperand();
  13325. inits.push({ value: initOperand });
  13326. isTied.push(true);
  13327. } else {
  13328. isTied.push(false);
  13329. }
  13330. if (!parser.parseOptionalComma()) {
  13331. break;
  13332. }
  13333. }
  13334. parser.parseRParen();
  13335. }
  13336. parser.parseLSquare();
  13337. while (parser.getToken().isNot(_.Token.r_square)) {
  13338. const indexArg = parser.parseOperand();
  13339. parser.parseColon();
  13340. const indexType = parser.parseType();
  13341. indexArgs.push({ value: indexArg, type: indexType });
  13342. if (!parser.parseOptionalComma()) {
  13343. break;
  13344. }
  13345. }
  13346. parser.parseRSquare();
  13347. if (regionRefArgs.length > 0 && parser.parseOptionalColon()) {
  13348. parser.parseLParen();
  13349. let refIdx = result.attributes.get('num_leading_args') || 0;
  13350. while (parser.getToken().isNot(_.Token.r_paren)) {
  13351. const refType = parser.parseType();
  13352. if (refIdx < regionRefArgs.length) {
  13353. regionRefArgs[refIdx].type = refType;
  13354. }
  13355. refIdx++;
  13356. if (!parser.parseOptionalComma()) {
  13357. break;
  13358. }
  13359. }
  13360. parser.parseRParen();
  13361. parser.parseArrow();
  13362. parser.parseLParen();
  13363. while (parser.getToken().isNot(_.Token.r_paren)) {
  13364. const resType = parser.parseType();
  13365. resultTypes.push(resType);
  13366. result.addTypes([resType]);
  13367. if (parser.parseOptionalLBrace()) {
  13368. while (parser.getToken().isNot(_.Token.r_brace)) {
  13369. const dim = parser.parseOperand();
  13370. dynamicSizes.push({ value: dim });
  13371. if (!parser.parseOptionalComma()) {
  13372. break;
  13373. }
  13374. }
  13375. parser.parseRBrace();
  13376. }
  13377. if (!parser.parseOptionalComma()) {
  13378. break;
  13379. }
  13380. }
  13381. parser.parseRParen();
  13382. }
  13383. for (const init of inits) {
  13384. parser.resolveOperand(init.value, null, result.operands);
  13385. }
  13386. for (const dim of dynamicSizes) {
  13387. parser.resolveOperand(dim.value, null, result.operands);
  13388. }
  13389. if (isTied.length > 0) {
  13390. result.addAttribute('is_tied', isTied);
  13391. }
  13392. const region = { blocks: [{ arguments: [...regionRefArgs, ...indexArgs], operations: [] }] };
  13393. parser.parseRegion(region);
  13394. result.regions.push(region);
  13395. }
  13396. };
  13397. _.IREEVectorExtDialect = class extends _.Dialect {
  13398. constructor(operations) {
  13399. super(operations, 'iree_vector_ext');
  13400. }
  13401. parseOperation(parser, result) {
  13402. if (result.op === 'iree_vector_ext.transfer_gather') {
  13403. const unresolvedSource = parser.parseOperand();
  13404. const unresolvedIndices = [];
  13405. parser.parseLSquare();
  13406. while (!parser.parseOptionalRSquare()) {
  13407. if (parser.getToken().is(_.Token.percent_identifier)) {
  13408. unresolvedIndices.push(parser.parseOperand());
  13409. }
  13410. parser.parseOptionalComma();
  13411. }
  13412. parser.parseLSquare();
  13413. const indexed = [];
  13414. const unresolvedIndexVecs = [];
  13415. const indexVecTypes = [];
  13416. while (!parser.parseOptionalRSquare()) {
  13417. if (parser.parseOptionalKeyword('None')) {
  13418. indexed.push(false);
  13419. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  13420. const indexVec = parser.parseOperand();
  13421. parser.parseColon();
  13422. const indexVecType = parser.parseType();
  13423. unresolvedIndexVecs.push(indexVec);
  13424. indexVecTypes.push(indexVecType);
  13425. indexed.push(true);
  13426. }
  13427. parser.parseOptionalComma();
  13428. }
  13429. result.addAttribute('indexed', indexed);
  13430. parser.parseComma();
  13431. const padding = parser.parseAttribute();
  13432. result.addAttribute('padding', padding);
  13433. let unresolvedMask = null;
  13434. if (parser.parseOptionalComma()) {
  13435. if (parser.getToken().is(_.Token.percent_identifier)) {
  13436. unresolvedMask = parser.parseOperand();
  13437. }
  13438. }
  13439. if (parser.getToken().is(_.Token.l_brace)) {
  13440. parser.parseAttributeDict(result.attributes);
  13441. }
  13442. let sourceType = null;
  13443. if (parser.parseOptionalColon()) {
  13444. sourceType = parser.parseType();
  13445. parser.parseComma();
  13446. const resultType = parser.parseType();
  13447. result.addTypes([resultType]);
  13448. }
  13449. parser.resolveOperand(unresolvedSource, sourceType, result.operands);
  13450. const indexType = new _.IndexType();
  13451. for (const idx of unresolvedIndices) {
  13452. parser.resolveOperand(idx, indexType, result.operands);
  13453. }
  13454. for (let i = 0; i < unresolvedIndexVecs.length; i++) {
  13455. parser.resolveOperand(unresolvedIndexVecs[i], indexVecTypes[i], result.operands);
  13456. }
  13457. if (unresolvedMask) {
  13458. parser.resolveOperand(unresolvedMask, null, result.operands);
  13459. }
  13460. return true;
  13461. }
  13462. return super.parseOperation(parser, result);
  13463. }
  13464. };
  13465. _.IREETensorExtDialect = class extends _.Dialect {
  13466. constructor(operations) {
  13467. super(operations, 'iree_tensor_ext');
  13468. }
  13469. parseType(parser, dialect) {
  13470. const typeName = parser.parseOptionalKeyword();
  13471. if (typeName === 'dispatch.tensor') {
  13472. let type = `!${dialect}.${typeName}`;
  13473. if (parser.getToken().is(_.Token.less)) {
  13474. const content = parser.skip('<');
  13475. type += content;
  13476. }
  13477. return new _.Type(type);
  13478. }
  13479. return null;
  13480. }
  13481. };
  13482. _.LinalgDialect = class extends _.Dialect {
  13483. constructor(operations) {
  13484. super(operations, 'linalg');
  13485. this._namedStructuredOps = new Set([
  13486. 'linalg.matmul', 'linalg.batch_matmul', 'linalg.batch_reduce_matmul',
  13487. 'linalg.matvec', 'linalg.vecmat', 'linalg.dot', 'linalg.batch_matvec',
  13488. 'linalg.conv_1d', 'linalg.conv_1d_ncw_fcw', 'linalg.conv_1d_nwc_wcf',
  13489. 'linalg.conv_2d', 'linalg.conv_2d_nchw_fchw', 'linalg.conv_2d_nchw_fchw_q',
  13490. 'linalg.conv_2d_ngchw_fgchw', 'linalg.conv_2d_ngchw_gfchw', 'linalg.conv_2d_ngchw_gfchw_q',
  13491. 'linalg.conv_2d_nhwc_fhwc', 'linalg.conv_2d_nhwc_fhwc_q',
  13492. 'linalg.conv_2d_nhwc_hwcf', 'linalg.conv_2d_nhwc_hwcf_q',
  13493. 'linalg.conv_2d_nhwgc_gfhwc', 'linalg.conv_2d_nhwgc_gfhwc_q',
  13494. 'linalg.conv_3d', 'linalg.conv_3d_ncdhw_fcdhw', 'linalg.conv_3d_ndhwc_dhwcf', 'linalg.conv_3d_ndhwc_dhwcf_q',
  13495. 'linalg.depthwise_conv_1d_ncw_cw', 'linalg.depthwise_conv_1d_nwc_wc', 'linalg.depthwise_conv_1d_nwc_wcm',
  13496. 'linalg.depthwise_conv_2d_nchw_chw', 'linalg.depthwise_conv_2d_nhwc_hwc', 'linalg.depthwise_conv_2d_nhwc_hwc_q',
  13497. 'linalg.depthwise_conv_2d_nhwc_hwcm', 'linalg.depthwise_conv_2d_nhwc_hwcm_q',
  13498. 'linalg.depthwise_conv_3d_ncdhw_cdhw', 'linalg.depthwise_conv_3d_ndhwc_dhwc', 'linalg.depthwise_conv_3d_ndhwc_dhwcm',
  13499. 'linalg.pooling_nchw_max', 'linalg.pooling_nchw_sum',
  13500. 'linalg.pooling_nhwc_max', 'linalg.pooling_nhwc_max_unsigned', 'linalg.pooling_nhwc_min', 'linalg.pooling_nhwc_min_unsigned', 'linalg.pooling_nhwc_sum',
  13501. 'linalg.pooling_ncw_max', 'linalg.pooling_ncw_sum',
  13502. 'linalg.pooling_nwc_max', 'linalg.pooling_nwc_max_unsigned', 'linalg.pooling_nwc_min', 'linalg.pooling_nwc_min_unsigned', 'linalg.pooling_nwc_sum',
  13503. 'linalg.pooling_ndhwc_max', 'linalg.pooling_ndhwc_min', 'linalg.pooling_ndhwc_sum'
  13504. ]);
  13505. }
  13506. parseOperation(parser, result) {
  13507. const opInfo = result.name.getRegisteredInfo();
  13508. if (result.op === 'linalg.generic') {
  13509. return this.parseGenericOp(parser, result);
  13510. }
  13511. if (result.op === 'linalg.init_tensor') {
  13512. if (parser.parseOptionalLSquare()) {
  13513. const dims = [];
  13514. while (parser.getToken().isNot(_.Token.r_square)) {
  13515. if (parser.getToken().is(_.Token.percent_identifier)) {
  13516. dims.push(parser.parseOperand().name);
  13517. } else if (parser.getToken().is(_.Token.integer)) {
  13518. dims.push(parser.getToken().getSpelling().str());
  13519. parser.consumeToken(_.Token.integer);
  13520. }
  13521. parser.parseOptionalComma();
  13522. }
  13523. parser.parseRSquare();
  13524. result.addAttribute('static_sizes', dims);
  13525. }
  13526. result.addTypes(parser.parseOptionalColonTypeList());
  13527. return true;
  13528. }
  13529. if (result.op === 'linalg.fill') {
  13530. // Form 1: ins/outs format - use parseNamedStructuredOp
  13531. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'ins' || parser.getToken().is(_.Token.l_brace) || parser.getToken().is(_.Token.less)) {
  13532. return this.parseNamedStructuredOp(parser, result);
  13533. }
  13534. let unresolvedOperands = [];
  13535. if (parser.parseOptionalLParen()) {
  13536. unresolvedOperands = parser.parseOperandList();
  13537. parser.parseRParen();
  13538. }
  13539. if (parser.getToken().is(_.Token.l_brace)) {
  13540. parser.parseAttributeDict(result.attributes);
  13541. }
  13542. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  13543. if (parser.parseOptionalArrow()) {
  13544. const types = parser.parseFunctionResultTypes();
  13545. result.addTypes(types);
  13546. }
  13547. return true;
  13548. }
  13549. if (result.op === 'linalg.conv') {
  13550. let unresolvedOperands = [];
  13551. if (parser.parseOptionalLParen()) {
  13552. unresolvedOperands = parser.parseOperandList();
  13553. parser.parseRParen();
  13554. }
  13555. if (parser.getToken().is(_.Token.l_brace)) {
  13556. parser.parseAttributeDict(result.attributes);
  13557. }
  13558. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  13559. return true;
  13560. }
  13561. if (result.op === 'linalg.yield') {
  13562. const unresolvedOperands = parser.parseOperandList();
  13563. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  13564. return true;
  13565. }
  13566. if (result.op === 'linalg.pack') {
  13567. return this.parsePackOp(parser, result);
  13568. }
  13569. if (result.op === 'linalg.unpack') {
  13570. return this.parseUnpackOp(parser, result);
  13571. }
  13572. if (result.op === 'linalg.transpose') {
  13573. return this.parseDstStyleOp(parser, result, (parser, attributes) => {
  13574. parser.parseDenseI64ArrayAttr('permutation', attributes);
  13575. });
  13576. }
  13577. if (result.op === 'linalg.reduce') {
  13578. // Optional short form: { payload_op attr-dict }
  13579. let payloadOpName = null;
  13580. const payloadOpAttrs = new Map();
  13581. if (parser.parseOptionalLBrace()) {
  13582. payloadOpName = parser.parseCustomOperationName();
  13583. if (parser.getToken().is(_.Token.l_brace)) {
  13584. parser.parseAttributeDict(payloadOpAttrs);
  13585. }
  13586. parser.parseRBrace();
  13587. }
  13588. if (!this.parseDstStyleOp(parser, result, (parser, attributes) => {
  13589. parser.parseDenseI64ArrayAttr('dimensions', attributes);
  13590. })) {
  13591. return false;
  13592. }
  13593. // Parse block arguments and region (or add body with payload op)
  13594. if (payloadOpName) {
  13595. this.addBodyWithPayloadOp(result, payloadOpName, payloadOpAttrs, true, true);
  13596. } else {
  13597. const regionArgs = [];
  13598. if (parser.getToken().is(_.Token.l_paren)) {
  13599. parser.parseLParen();
  13600. while (parser.getToken().isNot(_.Token.r_paren)) {
  13601. const value = parser.parseOperand();
  13602. parser.parseColon();
  13603. const type = parser.parseType();
  13604. regionArgs.push({ value, type });
  13605. if (!parser.parseOptionalComma()) {
  13606. break;
  13607. }
  13608. }
  13609. parser.parseRParen();
  13610. }
  13611. const region = result.addRegion();
  13612. if (parser.getToken().is(_.Token.l_brace)) {
  13613. parser.parseRegion(region, regionArgs);
  13614. }
  13615. }
  13616. return true;
  13617. }
  13618. if (result.op === 'linalg.broadcast') {
  13619. return this.parseDstStyleOp(parser, result, (parser, attributes) => {
  13620. parser.parseDenseI64ArrayAttr('dimensions', attributes);
  13621. });
  13622. }
  13623. if (result.op === 'linalg.elementwise') {
  13624. parser.parseKeyword('kind');
  13625. parser.parseEqual();
  13626. const kind = parser.parseAttribute();
  13627. result.addAttribute('kind', kind.value);
  13628. const indexingMapsAttr = this.parseIndexingMapsAttr(parser);
  13629. if (indexingMapsAttr !== null) {
  13630. result.addAttribute('indexing_maps', indexingMapsAttr);
  13631. }
  13632. return this.parseNamedStructuredOp(parser, result);
  13633. }
  13634. if (result.op === 'linalg.map') {
  13635. return this.parseMapOp(parser, result);
  13636. }
  13637. if (result.op === 'linalg.contract') {
  13638. const indexingMapsAttr = this.parseIndexingMapsAttr(parser);
  13639. if (!indexingMapsAttr) {
  13640. throw new mlir.Error(`Expected 'indexing_maps' attribute ${parser.location()}`);
  13641. }
  13642. result.addAttribute('indexing_maps', indexingMapsAttr);
  13643. return this.parseNamedStructuredOp(parser, result);
  13644. }
  13645. if (this._namedStructuredOps.has(result.op)) {
  13646. const indexingMapsAttr = this.parseIndexingMapsAttr(parser);
  13647. if (indexingMapsAttr) {
  13648. result.addAttribute('indexing_maps', indexingMapsAttr);
  13649. }
  13650. return this.parseNamedStructuredOp(parser, result);
  13651. }
  13652. if (opInfo.metadata && opInfo.metadata.assemblyFormat) {
  13653. return super.parseOperation(parser, result);
  13654. }
  13655. if (parser.getToken().is(_.Token.l_brace) || parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'ins' || parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'outs') {
  13656. const parsed = this.parseCommonStructuredOpParts(parser, result);
  13657. if (!parsed) {
  13658. return false;
  13659. }
  13660. if (parser.parseOptionalKeyword('attrs')) {
  13661. parser.parseEqual();
  13662. parser.parseAttributeDict(result.attributes);
  13663. } else if (parser.getToken().is(_.Token.l_brace) && parser.getTokenSpelling().str() !== '^') {
  13664. const saved = parser.save();
  13665. parser.parseLBrace();
  13666. if (parser.getToken().isNot(_.Token.percent_identifier) && parser.getToken().isNot(_.Token.bare_identifier)) {
  13667. parser.restore(saved);
  13668. } else {
  13669. parser.restore(saved);
  13670. parser.parseAttributeDict(result.attributes);
  13671. }
  13672. }
  13673. if (parser.parseOptionalArrow()) {
  13674. const types = parser.parseFunctionResultTypes();
  13675. result.addTypes(types);
  13676. }
  13677. // Parse region (for generic ops)
  13678. if (parser.getToken().is(_.Token.l_brace)) {
  13679. const region = result.addRegion();
  13680. parser.parseRegion(region, []);
  13681. }
  13682. return true;
  13683. }
  13684. return false;
  13685. }
  13686. // "Common parsing used for both named structured ops created by ods-gen and by
  13687. // manually defined C++ ops. Does not handle regions."
  13688. // Returns { inputTypes, outputTypes } on success, null on failure.
  13689. parseCommonStructuredOpParts(parser, result, addOperandSegmentSizes = true) {
  13690. if (parser.parseOptionalLess()) {
  13691. result.propertiesAttr = parser.parseAttribute();
  13692. parser.parseGreater();
  13693. }
  13694. if (parser.getToken().is(_.Token.l_brace)) {
  13695. parser.parseAttributeDict(result.attributes);
  13696. }
  13697. const inputTypes = [];
  13698. const outputTypes = [];
  13699. if (parser.parseOptionalKeyword('ins')) {
  13700. if (!parser.parseOptionalLParen()) {
  13701. return null;
  13702. }
  13703. const unresolvedIns = [];
  13704. while (parser.getToken().is(_.Token.percent_identifier)) {
  13705. unresolvedIns.push(parser.parseOperand());
  13706. if (!parser.parseOptionalComma()) {
  13707. break;
  13708. }
  13709. }
  13710. if (parser.parseOptionalColon()) {
  13711. while (parser.getToken().isNot(_.Token.r_paren)) {
  13712. inputTypes.push(parser.parseType());
  13713. if (!parser.parseOptionalComma()) {
  13714. break;
  13715. }
  13716. }
  13717. parser.resolveOperands(unresolvedIns, inputTypes, result.operands);
  13718. }
  13719. if (!parser.parseOptionalRParen()) {
  13720. return null;
  13721. }
  13722. }
  13723. if (parser.parseOptionalKeyword('outs')) {
  13724. if (!parser.parseOptionalLParen()) {
  13725. return null;
  13726. }
  13727. const unresolvedOuts = [];
  13728. while (parser.getToken().is(_.Token.percent_identifier)) {
  13729. unresolvedOuts.push(parser.parseOperand());
  13730. if (!parser.parseOptionalComma()) {
  13731. break;
  13732. }
  13733. }
  13734. if (parser.parseOptionalColon()) {
  13735. while (parser.getToken().isNot(_.Token.r_paren)) {
  13736. outputTypes.push(parser.parseType());
  13737. if (!parser.parseOptionalComma()) {
  13738. break;
  13739. }
  13740. }
  13741. parser.resolveOperands(unresolvedOuts, outputTypes, result.operands);
  13742. }
  13743. if (!parser.parseOptionalRParen()) {
  13744. return null;
  13745. }
  13746. }
  13747. if (addOperandSegmentSizes) {
  13748. result.addAttribute('operandSegmentSizes', [inputTypes.length, outputTypes.length]);
  13749. }
  13750. return { inputTypes, outputTypes };
  13751. }
  13752. parseNamedStructuredOp(parser, result) {
  13753. const parsed = this.parseCommonStructuredOpParts(parser, result);
  13754. if (!parsed) {
  13755. return false;
  13756. }
  13757. if (parser.getToken().is(_.Token.l_brace)) {
  13758. parser.parseAttributeDict(result.attributes);
  13759. }
  13760. if (parser.parseOptionalArrow()) {
  13761. const types = parser.parseFunctionResultTypes();
  13762. result.addTypes(types);
  13763. }
  13764. return true;
  13765. }
  13766. parseIndexingMapsAttr(parser) {
  13767. if (!parser.parseOptionalKeyword('indexing_maps')) {
  13768. return null;
  13769. }
  13770. parser.parseEqual();
  13771. return parser.parseAttribute();
  13772. }
  13773. parseDstStyleOp(parser, op, parseAttrsFn) {
  13774. const parsed = this.parseCommonStructuredOpParts(parser, op, false);
  13775. if (!parsed) {
  13776. return false;
  13777. }
  13778. for (const outputType of parsed.outputTypes) {
  13779. if (outputType instanceof _.RankedTensorType) {
  13780. op.addTypes([outputType]);
  13781. }
  13782. }
  13783. if (parseAttrsFn) {
  13784. parseAttrsFn(parser, op.attributes);
  13785. }
  13786. if (parser.getToken().is(_.Token.l_brace)) {
  13787. parser.parseAttributeDict(op.attributes);
  13788. }
  13789. return true;
  13790. }
  13791. addBodyWithPayloadOp(op, payloadOpName, payloadOpAttrs /*, initFirst, mapInit */) {
  13792. const region = op.addRegion();
  13793. const block = { operations: [], arguments: [] };
  13794. for (const operand of op.operands) {
  13795. if (operand && operand.type) {
  13796. const elemType = operand.type.elementType || operand.type;
  13797. block.arguments.push({ value: null, type: elemType });
  13798. }
  13799. }
  13800. const payloadState = new _.OperationState(null,payloadOpName);
  13801. if (op.operands.length > 0) {
  13802. const lastOperand = op.operands[op.operands.length - 1];
  13803. if (lastOperand && lastOperand.type) {
  13804. const elemType = lastOperand.type.elementType || lastOperand.type;
  13805. payloadState.types = [elemType];
  13806. }
  13807. }
  13808. for (const [name, value] of payloadOpAttrs) {
  13809. payloadState.attributes.set(name, value);
  13810. }
  13811. block.operations.push(_.Operation.create(payloadState));
  13812. const yieldState = new _.OperationState(null, this.getOperation('linalg.yield'));
  13813. block.operations.push(_.Operation.create(yieldState));
  13814. region.blocks = [block];
  13815. }
  13816. parseMapOp(parser, result) {
  13817. let payloadOpName = null;
  13818. const payloadOpAttrs = new Map();
  13819. if (parser.parseOptionalLBrace()) {
  13820. payloadOpName = parser.parseCustomOperationName();
  13821. if (parser.getToken().is(_.Token.l_brace)) {
  13822. parser.parseAttributeDict(payloadOpAttrs);
  13823. }
  13824. parser.parseRBrace();
  13825. }
  13826. if (!this.parseDstStyleOp(parser, result)) {
  13827. return false;
  13828. }
  13829. // Parse block arguments and region (or add body with payload op)
  13830. if (payloadOpName) {
  13831. if (result.operands.length > 0) {
  13832. this.addBodyWithPayloadOp(result, payloadOpName, payloadOpAttrs, false, false);
  13833. } else {
  13834. result.addRegion();
  13835. }
  13836. } else {
  13837. const regionArgs = [];
  13838. if (parser.getToken().is(_.Token.l_paren)) {
  13839. parser.parseLParen();
  13840. while (parser.getToken().isNot(_.Token.r_paren)) {
  13841. const value = parser.parseOperand();
  13842. parser.parseColon();
  13843. const type = parser.parseType();
  13844. regionArgs.push({ value, type });
  13845. if (!parser.parseOptionalComma()) {
  13846. break;
  13847. }
  13848. }
  13849. parser.parseRParen();
  13850. }
  13851. const region = result.addRegion();
  13852. if (parser.getToken().is(_.Token.l_brace)) {
  13853. parser.parseRegion(region, regionArgs);
  13854. }
  13855. }
  13856. return true;
  13857. }
  13858. parseGenericOp(parser, result) {
  13859. if (parser.getToken().is(_.Token.l_brace) || parser.getToken().is(_.Token.hash_identifier)) {
  13860. if (parser.getToken().is(_.Token.hash_identifier)) {
  13861. const attrRef = parser.getToken().getSpelling().str();
  13862. parser.consumeToken(_.Token.hash_identifier);
  13863. result.addAttribute('trait', attrRef);
  13864. } else {
  13865. parser.parseAttributeDict(result.attributes);
  13866. }
  13867. }
  13868. if (parser.getToken().is(_.Token.l_brace)) {
  13869. parser.parseAttributeDict(result.attributes);
  13870. }
  13871. if (parser.parseOptionalKeyword('ins')) {
  13872. parser.parseLParen();
  13873. const unresolvedIns = [];
  13874. while (parser.getToken().is(_.Token.percent_identifier)) {
  13875. unresolvedIns.push(parser.parseOperand());
  13876. if (!parser.parseOptionalComma()) {
  13877. break;
  13878. }
  13879. }
  13880. if (parser.parseOptionalColon()) {
  13881. const insTypes = [];
  13882. while (parser.getToken().isNot(_.Token.r_paren)) {
  13883. insTypes.push(parser.parseType());
  13884. if (!parser.parseOptionalComma()) {
  13885. break;
  13886. }
  13887. }
  13888. parser.resolveOperands(unresolvedIns, insTypes, result.operands);
  13889. }
  13890. parser.parseRParen();
  13891. }
  13892. if (parser.parseOptionalKeyword('outs')) {
  13893. parser.parseLParen();
  13894. const unresolvedOuts = [];
  13895. while (parser.getToken().is(_.Token.percent_identifier)) {
  13896. unresolvedOuts.push(parser.parseOperand());
  13897. if (!parser.parseOptionalComma()) {
  13898. break;
  13899. }
  13900. }
  13901. if (parser.parseOptionalColon()) {
  13902. const outsTypes = [];
  13903. while (parser.getToken().isNot(_.Token.r_paren)) {
  13904. outsTypes.push(parser.parseType());
  13905. if (!parser.parseOptionalComma()) {
  13906. break;
  13907. }
  13908. }
  13909. parser.resolveOperands(unresolvedOuts, outsTypes, result.operands);
  13910. }
  13911. parser.parseRParen();
  13912. }
  13913. if (parser.parseOptionalKeyword('attrs')) {
  13914. parser.parseEqual();
  13915. parser.parseAttributeDict(result.attributes);
  13916. }
  13917. if (parser.getToken().is(_.Token.l_brace)) {
  13918. const region = result.addRegion();
  13919. parser.parseRegion(region);
  13920. }
  13921. if (parser.parseOptionalArrow()) {
  13922. const hasParens = parser.getToken().is(_.Token.l_paren);
  13923. const types = hasParens ? parser.parseTypeListParens() : parser.parseFunctionResultTypes();
  13924. result.addTypes(types);
  13925. }
  13926. return true;
  13927. }
  13928. parsePackOp(parser, result) {
  13929. const unresolvedSource = parser.parseOperand();
  13930. let unresolvedPadding = null;
  13931. let paddingType = null;
  13932. if (parser.parseOptionalKeyword('padding_value')) {
  13933. parser.parseLParen();
  13934. unresolvedPadding = parser.parseOperand();
  13935. parser.parseColon();
  13936. paddingType = parser.parseType();
  13937. parser.parseRParen();
  13938. }
  13939. if (parser.parseOptionalKeyword('outer_dims_perm')) {
  13940. parser.parseEqual();
  13941. const outerDimsPerm = [];
  13942. parser.parseLSquare();
  13943. while (parser.getToken().isNot(_.Token.r_square)) {
  13944. outerDimsPerm.push(parser.getToken().getSpelling().str());
  13945. parser.consumeToken(_.Token.integer);
  13946. if (!parser.parseOptionalComma()) {
  13947. break;
  13948. }
  13949. }
  13950. parser.parseRSquare();
  13951. result.addAttribute('outer_dims_perm', outerDimsPerm.map((v) => BigInt(v)));
  13952. }
  13953. parser.parseKeyword('inner_dims_pos');
  13954. parser.parseEqual();
  13955. const innerDimsPos = [];
  13956. parser.parseLSquare();
  13957. while (parser.getToken().isNot(_.Token.r_square)) {
  13958. innerDimsPos.push(parser.getToken().getSpelling().str());
  13959. parser.consumeToken(_.Token.integer);
  13960. if (!parser.parseOptionalComma()) {
  13961. break;
  13962. }
  13963. }
  13964. parser.parseRSquare();
  13965. result.addAttribute('inner_dims_pos', innerDimsPos.map((v) => BigInt(v)));
  13966. parser.parseKeyword('inner_tiles');
  13967. parser.parseEqual();
  13968. const staticInnerTiles = [];
  13969. const dynamicTileOperands = [];
  13970. parser.parseLSquare();
  13971. while (parser.getToken().isNot(_.Token.r_square)) {
  13972. if (parser.getToken().is(_.Token.percent_identifier)) {
  13973. const operand = parser.parseOperand();
  13974. dynamicTileOperands.push(operand);
  13975. staticInnerTiles.push(_.ShapedType.kDynamic);
  13976. } else if (parser.getToken().is(_.Token.integer)) {
  13977. staticInnerTiles.push(BigInt(parser.getToken().getSpelling().str()));
  13978. parser.consumeToken(_.Token.integer);
  13979. }
  13980. if (!parser.parseOptionalComma()) {
  13981. break;
  13982. }
  13983. }
  13984. parser.parseRSquare();
  13985. result.addAttribute('static_inner_tiles', staticInnerTiles);
  13986. parser.parseKeyword('into');
  13987. const unresolvedDest = parser.parseOperand();
  13988. if (parser.getToken().is(_.Token.l_brace)) {
  13989. parser.parseAttributeDict(result.attributes);
  13990. }
  13991. parser.parseColon();
  13992. const sourceType = parser.parseType();
  13993. parser.parseArrow();
  13994. const destType = parser.parseType();
  13995. parser.resolveOperand(unresolvedSource, sourceType, result.operands);
  13996. parser.resolveOperand(unresolvedDest, destType, result.operands);
  13997. if (unresolvedPadding) {
  13998. parser.resolveOperand(unresolvedPadding, paddingType, result.operands);
  13999. }
  14000. for (const dynOp of dynamicTileOperands) {
  14001. parser.resolveOperand(dynOp, null, result.operands);
  14002. }
  14003. if (!sourceType.toString().startsWith('memref')) {
  14004. result.addTypes([destType]);
  14005. }
  14006. return true;
  14007. }
  14008. parseUnpackOp(parser, result) {
  14009. const unresolvedSource = parser.parseOperand();
  14010. if (parser.parseOptionalKeyword('outer_dims_perm')) {
  14011. parser.parseEqual();
  14012. const outerDimsPerm = [];
  14013. parser.parseLSquare();
  14014. while (parser.getToken().isNot(_.Token.r_square)) {
  14015. outerDimsPerm.push(parser.getToken().getSpelling().str());
  14016. parser.consumeToken(_.Token.integer);
  14017. if (!parser.parseOptionalComma()) {
  14018. break;
  14019. }
  14020. }
  14021. parser.parseRSquare();
  14022. result.addAttribute('outer_dims_perm', outerDimsPerm.map((v) => BigInt(v)));
  14023. }
  14024. parser.parseKeyword('inner_dims_pos');
  14025. parser.parseEqual();
  14026. const innerDimsPos = [];
  14027. parser.parseLSquare();
  14028. while (parser.getToken().isNot(_.Token.r_square)) {
  14029. innerDimsPos.push(parser.getToken().getSpelling().str());
  14030. parser.consumeToken(_.Token.integer);
  14031. if (!parser.parseOptionalComma()) {
  14032. break;
  14033. }
  14034. }
  14035. parser.parseRSquare();
  14036. result.addAttribute('inner_dims_pos', innerDimsPos.map((v) => BigInt(v)));
  14037. parser.parseKeyword('inner_tiles');
  14038. parser.parseEqual();
  14039. const staticInnerTiles = [];
  14040. const dynamicTileOperands = [];
  14041. parser.parseLSquare();
  14042. while (parser.getToken().isNot(_.Token.r_square)) {
  14043. if (parser.getToken().is(_.Token.percent_identifier)) {
  14044. const operand = parser.parseOperand();
  14045. dynamicTileOperands.push(operand);
  14046. staticInnerTiles.push(-9223372036854775808n); // ShapedType::kDynamic
  14047. } else if (parser.getToken().is(_.Token.integer)) {
  14048. staticInnerTiles.push(BigInt(parser.getToken().getSpelling().str()));
  14049. parser.consumeToken(_.Token.integer);
  14050. }
  14051. if (!parser.parseOptionalComma()) {
  14052. break;
  14053. }
  14054. }
  14055. parser.parseRSquare();
  14056. result.addAttribute('static_inner_tiles', staticInnerTiles);
  14057. parser.parseKeyword('into');
  14058. const unresolvedDest = parser.parseOperand();
  14059. if (parser.getToken().is(_.Token.l_brace)) {
  14060. parser.parseAttributeDict(result.attributes);
  14061. }
  14062. parser.parseColon();
  14063. const sourceType = parser.parseType();
  14064. parser.parseArrow();
  14065. const destType = parser.parseType();
  14066. parser.resolveOperand(unresolvedSource, sourceType, result.operands);
  14067. parser.resolveOperand(unresolvedDest, destType, result.operands);
  14068. for (const dynOp of dynamicTileOperands) {
  14069. parser.resolveOperand(dynOp, null, result.operands);
  14070. }
  14071. if (!sourceType.toString().startsWith('memref')) {
  14072. result.addTypes([destType]);
  14073. }
  14074. return true;
  14075. }
  14076. };
  14077. _.ONNXDialect = class extends _.Dialect {
  14078. constructor(operations) {
  14079. super(operations, 'onnx');
  14080. }
  14081. parseOperation(parser, result) {
  14082. if (result.op === 'onnx.Constant') {
  14083. parser.parseOptionalAttrDict(result.attributes);
  14084. if (result.attributes.size === 0) {
  14085. const value = parser.parseOptionalAttribute();
  14086. if (value) {
  14087. const name = value instanceof _.SparseElementsAttr ? 'sparse_value' : 'value';
  14088. result.addAttribute(name, value);
  14089. result.addTypes([value.type]);
  14090. return true;
  14091. }
  14092. }
  14093. result.addTypes([parser.parseColonType()]);
  14094. return true;
  14095. }
  14096. if (result.op === 'onnx.ConstantOfShape') {
  14097. parser.parseLParen();
  14098. const unresolved = parser.parseOperand();
  14099. parser.parseRParen();
  14100. parser.parseOptionalAttrDict(result.attributes);
  14101. parser.parseColon();
  14102. parser.parseLParen();
  14103. const inputType = parser.parseType();
  14104. parser.resolveOperand(unresolved, inputType, result.operands);
  14105. parser.parseRParen();
  14106. parser.parseArrow();
  14107. const outputType = parser.parseType();
  14108. result.addTypes([outputType]);
  14109. return true;
  14110. }
  14111. return super.parseOperation(parser, result);
  14112. }
  14113. };
  14114. _.KrnlDialect = class extends _.Dialect {
  14115. constructor(operations) {
  14116. super(operations, 'krnl');
  14117. }
  14118. parseOperation(parser, result) {
  14119. if (result.op === 'krnl.define_loops') {
  14120. if (parser.getToken().is(_.Token.integer)) {
  14121. const count = parseInt(parser.getToken().getSpelling().str(), 10);
  14122. parser.consumeToken(_.Token.integer);
  14123. result.addAttribute('num_loops', count);
  14124. const loopType = new _.Type('!krnl.loop');
  14125. const types = Array(count).fill(loopType);
  14126. result.addTypes(types);
  14127. }
  14128. return true;
  14129. }
  14130. if (result.op === 'krnl.get_linear_offset_index') {
  14131. const unresolvedOperands = [];
  14132. const staticIndices = [];
  14133. const memref = parser.parseOperand();
  14134. unresolvedOperands.push(memref);
  14135. if (parser.parseOptionalKeyword('at')) {
  14136. parser.parseLSquare();
  14137. while (parser.getToken().isNot(_.Token.r_square)) {
  14138. // Indices can be either SSA values (%arg) or integer constants (0, 10, etc.)
  14139. if (parser.getToken().is(_.Token.percent_identifier)) {
  14140. const index = parser.parseOperand();
  14141. unresolvedOperands.push(index);
  14142. staticIndices.push(-9223372036854775808n); // ShapedType::kDynamic marker
  14143. } else if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus)) {
  14144. const value = parser.parseInteger();
  14145. staticIndices.push(BigInt(value));
  14146. }
  14147. if (parser.getToken().isNot(_.Token.r_square)) {
  14148. parser.parseOptionalComma();
  14149. }
  14150. }
  14151. parser.parseRSquare();
  14152. if (staticIndices.length > 0) {
  14153. result.addAttribute('static_indices', staticIndices);
  14154. }
  14155. }
  14156. let type = null;
  14157. if (parser.parseOptionalColon()) {
  14158. type = parser.parseType();
  14159. }
  14160. for (const unresolved of unresolvedOperands) {
  14161. parser.resolveOperand(unresolved, type, result.operands);
  14162. }
  14163. result.addTypes([new _.IndexType()]);
  14164. return true;
  14165. }
  14166. if (result.op === 'krnl.prefetch') {
  14167. const unresolvedOperands = [];
  14168. const memref = parser.parseOperand();
  14169. unresolvedOperands.push(memref);
  14170. if (parser.parseOptionalLSquare()) {
  14171. while (parser.getToken().isNot(_.Token.r_square)) {
  14172. const index = parser.parseOperand();
  14173. unresolvedOperands.push(index);
  14174. if (parser.getToken().isNot(_.Token.r_square)) {
  14175. parser.parseOptionalComma();
  14176. }
  14177. }
  14178. parser.parseRSquare();
  14179. }
  14180. parser.parseComma();
  14181. const readOrWrite = parser.getToken().getSpelling().str();
  14182. parser.consumeToken(_.Token.bare_identifier);
  14183. result.addAttribute('isWrite', readOrWrite === 'write');
  14184. parser.parseComma();
  14185. parser.parseKeyword('locality');
  14186. parser.parseLess();
  14187. const localityHint = parser.parseInteger();
  14188. result.addAttribute('localityHint', localityHint);
  14189. parser.parseGreater();
  14190. parser.parseComma();
  14191. const cacheType = parser.getToken().getSpelling().str();
  14192. parser.consumeToken(_.Token.bare_identifier);
  14193. result.addAttribute('isDataCache', cacheType === 'data');
  14194. parser.parseOptionalAttrDict(result.attributes);
  14195. let type = null;
  14196. if (parser.parseOptionalColon()) {
  14197. type = parser.parseType();
  14198. }
  14199. for (const unresolved of unresolvedOperands) {
  14200. parser.resolveOperand(unresolved, type, result.operands);
  14201. }
  14202. return true;
  14203. }
  14204. if (result.op === 'krnl.iterate') {
  14205. const unresolvedOperands = parser.parseOperandList('paren');
  14206. for (const operand of unresolvedOperands) {
  14207. parser.resolveOperand(operand, null, result.operands);
  14208. }
  14209. if (parser.parseOptionalKeyword('with')) {
  14210. parser.parseLParen();
  14211. const numOptimizedLoops = result.operands.length;
  14212. while (parser.getToken().isNot(_.Token.r_paren)) {
  14213. parser.parseOperand();
  14214. parser.parseArrow();
  14215. parser.parseOperand();
  14216. parser.parseEqual();
  14217. parser.parseOptionalKeyword('max');
  14218. if (parser.getToken().isAny(_.Token.kw_affine_map, _.Token.kw_affine_set)) {
  14219. parser.parseAttribute();
  14220. if (parser.getToken().is(_.Token.l_paren)) {
  14221. parser.skip('(');
  14222. }
  14223. if (parser.getToken().is(_.Token.l_square)) {
  14224. parser.skip('[');
  14225. }
  14226. } else {
  14227. parser.parseAttribute();
  14228. }
  14229. parser.parseKeyword('to');
  14230. parser.parseOptionalKeyword('min');
  14231. if (parser.getToken().isAny(_.Token.kw_affine_map, _.Token.kw_affine_set)) {
  14232. parser.parseAttribute();
  14233. if (parser.getToken().is(_.Token.l_paren)) {
  14234. parser.skip('(');
  14235. }
  14236. if (parser.getToken().is(_.Token.l_square)) {
  14237. parser.skip('[');
  14238. }
  14239. } else {
  14240. parser.parseAttribute();
  14241. }
  14242. if (parser.getToken().isNot(_.Token.r_paren)) {
  14243. parser.parseOptionalComma();
  14244. }
  14245. }
  14246. parser.parseRParen();
  14247. result.addAttribute('num_optimized_loops', numOptimizedLoops);
  14248. }
  14249. if (parser.parseOptionalKeyword('iter_args')) {
  14250. parser.parseLParen();
  14251. while (parser.getToken().isNot(_.Token.r_paren)) {
  14252. parser.parseOperand();
  14253. parser.parseEqual();
  14254. parser.parseAttribute();
  14255. if (parser.getToken().isNot(_.Token.r_paren)) {
  14256. parser.parseOptionalComma();
  14257. }
  14258. }
  14259. parser.parseRParen();
  14260. if (parser.parseOptionalArrow()) {
  14261. const types = parser.parseFunctionResultTypes();
  14262. result.addTypes(types);
  14263. }
  14264. }
  14265. if (parser.getToken().is(_.Token.l_brace)) {
  14266. const region = {};
  14267. parser.parseRegion(region);
  14268. result.regions = [region];
  14269. }
  14270. return true;
  14271. }
  14272. return super.parseOperation(parser, result);
  14273. }
  14274. };
  14275. _.MhloDialect = class extends _.HLODialect {
  14276. constructor(operations) {
  14277. super(operations, 'mhlo');
  14278. }
  14279. parseOperation(parser, result) {
  14280. const opInfo = result.name.getRegisteredInfo();
  14281. if (opInfo.metadata && opInfo.metadata.parser && opInfo.metadata.parser.includes('parseOneResultSameOperandTypeOp')) {
  14282. return this.parseOneResultSameOperandTypeOp(parser, result);
  14283. }
  14284. if (result.op === 'mhlo.constant') {
  14285. if (parser.parseOptionalLParen() && parser.parseOptionalRParen()) {
  14286. if (parser.getToken().is(_.Token.l_brace)) {
  14287. parser.parseAttributeDict(result.attributes);
  14288. }
  14289. if (parser.parseOptionalColon()) {
  14290. parser.parseLParen();
  14291. parser.parseRParen();
  14292. parser.parseArrow();
  14293. const type = parser.parseType();
  14294. result.addTypes([type]);
  14295. }
  14296. } else {
  14297. if (parser.getToken().is(_.Token.l_brace)) {
  14298. parser.parseAttributeDict(result.attributes);
  14299. }
  14300. const value = parser.parseAttribute();
  14301. if (value) {
  14302. result.addAttribute('value', value);
  14303. if (value.type && result.types.length === 0) {
  14304. result.addTypes([value.type]);
  14305. }
  14306. }
  14307. if (result.types.length === 0) {
  14308. result.addTypes(parser.parseOptionalColonTypeList());
  14309. }
  14310. }
  14311. return true;
  14312. }
  14313. if (result.op === 'mhlo.compare') {
  14314. // Use modern assemblyFormat if available, but only if this is modern syntax
  14315. // Old format has 'attributes' keyword, new format has attr-dict directly
  14316. if (opInfo.metadata && opInfo.metadata.assemblyFormat && !(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'attributes')) {
  14317. return super.parseOperation(parser, result);
  14318. }
  14319. // Legacy parser for old mhlo.compare without assembly format
  14320. if (parser.getToken().is(_.Token.bare_identifier)) {
  14321. const comparisonDirection = parser.getToken().getSpelling().str();
  14322. parser.consumeToken(_.Token.bare_identifier);
  14323. result.addAttribute('comparison_direction', comparisonDirection);
  14324. parser.parseComma();
  14325. const unresolvedOperands = parser.parseOperandList();
  14326. // Check for optional compare_type
  14327. if (parser.parseOptionalComma() && parser.getToken().is(_.Token.bare_identifier)) {
  14328. const compareType = parser.getToken().getSpelling().str();
  14329. parser.consumeToken(_.Token.bare_identifier);
  14330. result.addAttribute('compare_type', compareType);
  14331. }
  14332. parser.parseOptionalAttrDict(result.attributes);
  14333. if (parser.parseOptionalColon()) {
  14334. const type = parser.parseType();
  14335. if (type instanceof _.FunctionType) {
  14336. parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);
  14337. result.addTypes(type.results);
  14338. } else {
  14339. // Single type applied to all operands
  14340. const types = unresolvedOperands.map(() => type);
  14341. parser.resolveOperands(unresolvedOperands, types, result.operands);
  14342. }
  14343. } else {
  14344. for (const operand of unresolvedOperands) {
  14345. parser.resolveOperand(operand, null, result.operands);
  14346. }
  14347. }
  14348. return true;
  14349. }
  14350. }
  14351. if (result.op === 'mhlo.reduce') {
  14352. // mhlo uses raw array for dimensions (like b.getI64TensorAttr in ref impl)
  14353. return super.parseReduceOp(parser, result, (dims) => dims, 'mhlo.return');
  14354. }
  14355. if (result.op === 'mhlo.scan' && parser.getToken().is(_.Token.l_paren)) {
  14356. return super.parseScanOp(parser, result, 'mhlo.return');
  14357. }
  14358. if (result.op === 'mhlo.while') {
  14359. // mhlo.while always uses parenthesized form with named arguments
  14360. parser.parseLParen();
  14361. const unresolvedOperands = [];
  14362. while (parser.getToken().isNot(_.Token.r_paren)) {
  14363. const firstOperand = parser.parseOperand();
  14364. let operandToResolve = firstOperand;
  14365. if (parser.parseOptionalEqual()) {
  14366. operandToResolve = parser.parseOperand();
  14367. }
  14368. unresolvedOperands.push(operandToResolve);
  14369. parser.parseOptionalComma();
  14370. }
  14371. parser.parseRParen();
  14372. const types = [];
  14373. if (parser.parseOptionalColon()) {
  14374. while (!(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'cond') && !(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'attributes')) {
  14375. types.push(parser.parseType());
  14376. if (!parser.parseOptionalComma()) {
  14377. break;
  14378. }
  14379. }
  14380. }
  14381. parser.resolveOperands(unresolvedOperands, types, result.operands);
  14382. result.addTypes(types);
  14383. if (parser.parseOptionalKeyword('attributes')) {
  14384. if (parser.getToken().is(_.Token.l_brace)) {
  14385. parser.parseAttributeDict(result.attributes);
  14386. }
  14387. }
  14388. if (parser.parseOptionalKeyword('cond')) {
  14389. const condRegion = {};
  14390. parser.parseRegion(condRegion);
  14391. result.regions.push(condRegion);
  14392. }
  14393. if (parser.parseOptionalKeyword('do')) {
  14394. const bodyRegion = {};
  14395. parser.parseRegion(bodyRegion);
  14396. result.regions.push(bodyRegion);
  14397. }
  14398. return true;
  14399. }
  14400. return super.parseOperation(parser, result);
  14401. }
  14402. parseOneResultSameOperandTypeOp(parser, result) {
  14403. const unresolvedOperands = parser.parseOperandList();
  14404. parser.parseOptionalAttrDict(result.attributes);
  14405. if (parser.parseOptionalColon()) {
  14406. const type = parser.parseType();
  14407. const types = unresolvedOperands.map(() => type);
  14408. parser.resolveOperands(unresolvedOperands, types, result.operands);
  14409. if (result.types.length > 0) {
  14410. result.types[0] = type;
  14411. }
  14412. } else {
  14413. for (const operand of unresolvedOperands) {
  14414. parser.resolveOperand(operand, null, result.operands);
  14415. }
  14416. }
  14417. return true;
  14418. }
  14419. };
  14420. _.ChloDialect = class extends _.HLODialect {
  14421. constructor(operations) {
  14422. super(operations, 'chlo');
  14423. }
  14424. parseOperation(parser, result) {
  14425. if (result.op === 'chlo.scan' && parser.getToken().is(_.Token.l_paren)) {
  14426. return super.parseScanOp(parser, result, 'stablehlo.return');
  14427. }
  14428. return super.parseOperation(parser, result);
  14429. }
  14430. };
  14431. _.THLODialect = class extends _.Dialect {
  14432. constructor(operations) {
  14433. super(operations, 'thlo');
  14434. }
  14435. parseOperation(parser, result) {
  14436. const opInfo = result.name.getRegisteredInfo();
  14437. if (opInfo.metadata.assemblyFormat) {
  14438. return super.parseOperation(parser, result);
  14439. }
  14440. if (parser.parseOptionalKeyword('ins')) {
  14441. parser.parseLParen();
  14442. while (parser.getToken().is(_.Token.percent_identifier)) {
  14443. const operand = parser.parseOperand();
  14444. let type = null;
  14445. if (parser.parseOptionalColon()) {
  14446. type = parser.parseType();
  14447. }
  14448. parser.resolveOperand(operand, type, result.operands);
  14449. if (!parser.parseOptionalComma()) {
  14450. break;
  14451. }
  14452. }
  14453. parser.parseRParen();
  14454. }
  14455. if (parser.parseOptionalKeyword('outs')) {
  14456. parser.parseLParen();
  14457. while (parser.getToken().is(_.Token.percent_identifier)) {
  14458. const operand = parser.parseOperand();
  14459. let type = null;
  14460. if (parser.parseOptionalColon()) {
  14461. type = parser.parseType();
  14462. }
  14463. parser.resolveOperand(operand, type, result.operands);
  14464. if (!parser.parseOptionalComma()) {
  14465. break;
  14466. }
  14467. }
  14468. parser.parseRParen();
  14469. }
  14470. if (parser.getToken().is(_.Token.l_brace)) {
  14471. parser.parseAttributeDict(result.attributes);
  14472. }
  14473. const blockArguments = [];
  14474. if (parser.getToken().is(_.Token.l_paren)) {
  14475. parser.parseLParen();
  14476. while (parser.getToken().isNot(_.Token.r_paren)) {
  14477. const value = parser.parseOperand();
  14478. parser.parseColon();
  14479. const type = parser.parseType();
  14480. blockArguments.push({ value, type });
  14481. if (!parser.parseOptionalComma()) {
  14482. break;
  14483. }
  14484. }
  14485. parser.parseRParen();
  14486. }
  14487. if (parser.getToken().is(_.Token.l_brace)) {
  14488. const region = { blocks: [] };
  14489. const block = { operations: [], arguments: blockArguments };
  14490. parser.parseLBrace();
  14491. while (!parser.parseOptionalRBrace()) {
  14492. const operation = parser.parseOperation();
  14493. block.operations.push(_.Operation.create(operation));
  14494. }
  14495. region.blocks.push(block);
  14496. result.regions.push(region);
  14497. }
  14498. return true;
  14499. }
  14500. };
  14501. _.QuantDialect = class extends _.Dialect {
  14502. constructor(operations) {
  14503. super(operations, 'quant');
  14504. }
  14505. parseType(parser, dialect) {
  14506. const typeName = parser.parseOptionalKeyword();
  14507. if (typeName === 'uniform' || typeName === 'calibrated' || typeName === 'any') {
  14508. let type = `!${dialect}.${typeName}`;
  14509. if (parser.getToken().is(_.Token.less)) {
  14510. const content = parser.skip('<');
  14511. type += content;
  14512. }
  14513. return new _.Type(type);
  14514. }
  14515. return null;
  14516. }
  14517. };
  14518. _.TosaDialect = class extends _.Dialect {
  14519. constructor(operations) {
  14520. super(operations, 'tosa');
  14521. this._customOps = new Set([
  14522. 'tosa.apply_scale', 'tosa.argmax', 'tosa.cast_from_block_scaled',
  14523. 'tosa.cast_to_block_scaled', 'tosa.clamp', 'tosa.conv2d_block_scaled',
  14524. 'tosa.matmul_t_block_scaled', 'tosa.max_pool2d', 'tosa.maximum',
  14525. 'tosa.minimum', 'tosa.reduce_max', 'tosa.reduce_min', 'tosa.rescale',
  14526. 'tosa.resize'
  14527. ]);
  14528. this._regionOps = new Set(['tosa.cond_if', 'tosa.while_loop']);
  14529. this.registerCustomDirective('VariableOpTypeOrInitialValue', this.parseVariableOpTypeOrInitialValue.bind(this));
  14530. }
  14531. parseType(parser, dialect) {
  14532. const typeName = parser.parseOptionalKeyword();
  14533. if (typeName === 'shape') {
  14534. let type = `!${dialect}.${typeName}`;
  14535. if (parser.getToken().is(_.Token.less)) {
  14536. const content = parser.skip('<');
  14537. type += content;
  14538. }
  14539. return new _.Type(type);
  14540. }
  14541. if (typeName === 'mxint8') {
  14542. return new _.Type(`!${dialect}.mxint8`);
  14543. }
  14544. return null;
  14545. }
  14546. parseOperation(parser, result) {
  14547. const opInfo = result.name.getRegisteredInfo();
  14548. if (this._regionOps.has(result.op)) {
  14549. let hasBlockArgs = false;
  14550. const unresolvedCond = [];
  14551. const unresolvedInputs = [];
  14552. const blockArgs = [];
  14553. if (parser.getToken().is(_.Token.percent_identifier)) {
  14554. unresolvedCond.push(parser.parseOperand());
  14555. }
  14556. if (parser.parseOptionalLParen()) {
  14557. hasBlockArgs = true;
  14558. while (parser.getToken().isNot(_.Token.r_paren)) {
  14559. if (parser.getToken().is(_.Token.percent_identifier)) {
  14560. blockArgs.push(parser.parseOperand());
  14561. parser.parseEqual();
  14562. unresolvedInputs.push(parser.parseOperand());
  14563. }
  14564. if (!parser.parseOptionalComma()) {
  14565. break;
  14566. }
  14567. }
  14568. parser.parseRParen();
  14569. }
  14570. if (parser.parseOptionalColon()) {
  14571. // For tosa.while_loop: no condition operand, has block args, function type after colon
  14572. if (unresolvedCond.length === 0 && hasBlockArgs) {
  14573. const functionType = parser.parseFunctionType();
  14574. if (functionType) {
  14575. parser.resolveOperands(unresolvedInputs, functionType.inputs, result.operands);
  14576. result.addTypes(functionType.results);
  14577. }
  14578. } else {
  14579. const condType = parser.parseType();
  14580. if (unresolvedCond.length > 0) {
  14581. parser.resolveOperands(unresolvedCond, [condType], result.operands);
  14582. }
  14583. // If block args present, parse function type for inputs/outputs
  14584. if (hasBlockArgs && parser.getToken().is(_.Token.l_paren)) {
  14585. const functionType = parser.parseFunctionType();
  14586. if (functionType) {
  14587. parser.resolveOperands(unresolvedInputs, functionType.inputs, result.operands);
  14588. result.addTypes(functionType.results);
  14589. }
  14590. } else if (parser.parseOptionalArrow()) {
  14591. const resultTypes = parser.parseFunctionResultTypes();
  14592. result.addTypes(resultTypes);
  14593. }
  14594. }
  14595. } else {
  14596. for (const cond of unresolvedCond) {
  14597. parser.resolveOperand(cond, null, result.operands);
  14598. }
  14599. for (const input of unresolvedInputs) {
  14600. parser.resolveOperand(input, null, result.operands);
  14601. }
  14602. }
  14603. if (parser.getToken().is(_.Token.l_brace)) {
  14604. const region = result.addRegion();
  14605. parser.parseRegion(region);
  14606. }
  14607. if (parser.parseOptionalKeyword('else') || parser.parseOptionalKeyword('do')) {
  14608. if (parser.getToken().is(_.Token.l_brace)) {
  14609. const secondRegion = {};
  14610. parser.parseRegion(secondRegion);
  14611. result.regions.push(secondRegion);
  14612. }
  14613. }
  14614. return true;
  14615. }
  14616. if (this._customOps.has(result.op)) {
  14617. const unresolvedOperands = parser.parseOperandList();
  14618. if (parser.getToken().is(_.Token.l_brace)) {
  14619. // Parse attribute dict but check if any are actually inputs
  14620. const inputNames = new Set((opInfo.metadata && opInfo.metadata.operands || []).map((i) => i.name));
  14621. const tempAttrs = new Map();
  14622. parser.parseAttributeDict(tempAttrs);
  14623. for (const [name, value] of tempAttrs) {
  14624. // If this is an input (like input_zp, output_zp), add as operand
  14625. if (inputNames.has(name) && value && typeof value === 'string' && value.startsWith('%')) {
  14626. const unresolvedOperand = new _.UnresolvedOperand(null,value, 0);
  14627. unresolvedOperands.push(unresolvedOperand);
  14628. } else if (inputNames.has(name) && value && value.value && typeof value.value === 'string' && value.value.startsWith('%')) {
  14629. const unresolvedOperand = new _.UnresolvedOperand(null, value.value, 0);
  14630. unresolvedOperands.push(unresolvedOperand);
  14631. } else {
  14632. result.attributes.set(name, value);
  14633. }
  14634. }
  14635. }
  14636. if (parser.parseOptionalColon()) {
  14637. const type = parser.parseType();
  14638. if (type instanceof _.FunctionType) {
  14639. parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);
  14640. result.addTypes(type.results);
  14641. } else {
  14642. const types = unresolvedOperands.map(() => type);
  14643. parser.resolveOperands(unresolvedOperands, types, result.operands);
  14644. if (parser.parseOptionalArrow()) {
  14645. const resultTypes = parser.parseFunctionResultTypes();
  14646. result.addTypes(resultTypes);
  14647. }
  14648. }
  14649. } else {
  14650. for (const operand of unresolvedOperands) {
  14651. parser.resolveOperand(operand, null, result.operands);
  14652. }
  14653. }
  14654. return true;
  14655. }
  14656. return super.parseOperation(parser, result);
  14657. }
  14658. parseVariableOpTypeOrInitialValue(parser, op /*, args */) {
  14659. if (parser.parseOptionalEqual()) {
  14660. const initialValue = parser.parseAttribute();
  14661. op.addAttribute('initial_value', initialValue);
  14662. } else if (parser.parseOptionalColon()) {
  14663. const type = parser.parseType();
  14664. op.addAttribute('type', type);
  14665. }
  14666. }
  14667. };
  14668. _.IRDLDialect = class extends _.Dialect {
  14669. constructor(operations) {
  14670. super(operations, 'irdl');
  14671. this.registerCustomDirective('SingleBlockRegion', this.parseSingleBlockRegion.bind(this));
  14672. this.registerCustomDirective('NamedValueList', this.parseNamedValueList.bind(this));
  14673. this.registerCustomDirective('NamedValueListWithVariadicity', this.parseNamedValueListWithVariadicity.bind(this));
  14674. this.registerCustomDirective('AttributesOp', this.parseAttributesOp.bind(this));
  14675. }
  14676. parseSingleBlockRegion(parser, op, /* args */) {
  14677. if (parser.getToken().is(_.Token.l_brace)) {
  14678. const region = op.addRegion();
  14679. parser.parseRegion(region);
  14680. }
  14681. }
  14682. parseNamedValueList(parser, op, argsAttrName, namesAttrName) {
  14683. const argValues = [];
  14684. const nameValues = [];
  14685. const parseOne = () => {
  14686. const name = parser.getToken().getSpelling().str();
  14687. parser.consumeToken();
  14688. nameValues.push(name);
  14689. parser.parseColon();
  14690. const value = parser.parseOperand();
  14691. argValues.push(value);
  14692. return value;
  14693. };
  14694. parser.parseCommaSeparatedList('paren', parseOne);
  14695. if (argsAttrName && namesAttrName) {
  14696. // args contains SSA values (%0, %1, ...) - resolve and add as operands
  14697. for (const value of argValues) {
  14698. parser.resolveOperand(value, null, op.operands);
  14699. }
  14700. op.addAttribute(namesAttrName, nameValues);
  14701. }
  14702. }
  14703. parseNamedValueListWithVariadicity(parser, op, argsAttrName, namesAttrName, variadicityAttrName) {
  14704. const argValues = [];
  14705. const nameValues = [];
  14706. const variadicityValues = [];
  14707. const parseOne = () => {
  14708. let variadicity = null;
  14709. if (parser.getToken().is(_.Token.bare_identifier)) {
  14710. const peekValue = parser.getTokenSpelling().str();
  14711. if (peekValue === 'single' || peekValue === 'optional' || peekValue === 'variadic') {
  14712. variadicity = parser.getToken().getSpelling().str();
  14713. parser.consumeToken(_.Token.bare_identifier);
  14714. }
  14715. }
  14716. const name = parser.getToken().getSpelling().str();
  14717. parser.consumeToken();
  14718. nameValues.push(name);
  14719. parser.parseColon();
  14720. const value = parser.parseOperand();
  14721. argValues.push(value);
  14722. variadicityValues.push(variadicity || 'single');
  14723. return value;
  14724. };
  14725. parser.parseCommaSeparatedList('paren', parseOne);
  14726. if (argsAttrName && namesAttrName) {
  14727. // args contains SSA values (%0, %1, ...) - resolve and add as operands
  14728. for (const value of argValues) {
  14729. parser.resolveOperand(value, null, op.operands);
  14730. }
  14731. op.addAttribute(namesAttrName, nameValues);
  14732. if (variadicityAttrName) {
  14733. op.addAttribute(variadicityAttrName, variadicityValues);
  14734. }
  14735. }
  14736. }
  14737. parseAttributesOp(parser, op, argsAttrName, namesAttrName) {
  14738. const argValues = [];
  14739. const nameValues = [];
  14740. if (parser.parseOptionalLBrace()) {
  14741. while (parser.getToken().isNot(_.Token.r_brace)) {
  14742. const name = parser.getToken().getSpelling().str();
  14743. parser.consumeToken(_.Token.string);
  14744. nameValues.push(name);
  14745. parser.parseEqual();
  14746. const value = parser.parseOperand();
  14747. argValues.push(value);
  14748. parser.parseOptionalComma();
  14749. }
  14750. parser.parseRBrace();
  14751. }
  14752. if (argsAttrName && namesAttrName) {
  14753. for (const value of argValues) {
  14754. parser.resolveOperand(value, null, op.operands);
  14755. }
  14756. op.addAttribute(namesAttrName, nameValues);
  14757. }
  14758. }
  14759. };
  14760. _.XeGPUDialect = class extends _.Dialect {
  14761. constructor(operations) {
  14762. super(operations, 'xegpu');
  14763. this.registerCustomDirective('OptionalDynamicIndexList', this.parseOptionalDynamicIndexList.bind(this));
  14764. }
  14765. parseOptionalDynamicIndexList(parser, op, dynamicAttrName, staticAttrName) {
  14766. const indices = [];
  14767. const dynamicValues = [];
  14768. if (parser.parseOptionalLSquare()) {
  14769. while (parser.getToken().isNot(_.Token.r_square)) {
  14770. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.floatliteral)) {
  14771. indices.push(parseInt(parser.getToken().getSpelling().str(), 10));
  14772. parser.consumeToken();
  14773. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  14774. const value = parser.parseOperand();
  14775. dynamicValues.push(value);
  14776. indices.push(-9223372036854775808);
  14777. } else {
  14778. break;
  14779. }
  14780. parser.parseOptionalComma();
  14781. }
  14782. parser.parseOptionalRSquare();
  14783. if (dynamicAttrName && staticAttrName) {
  14784. // Dynamic values are SSA operands (%0, %1, ...) - resolve and add as operands
  14785. for (const value of dynamicValues) {
  14786. parser.resolveOperand(value, null, op.operands);
  14787. }
  14788. // Static indices are compile-time constants - add as attribute
  14789. if (indices.length > 0) {
  14790. op.addAttribute(staticAttrName, indices);
  14791. }
  14792. }
  14793. }
  14794. }
  14795. };
  14796. _.ShardDialect = class extends _.Dialect {
  14797. constructor(operations) {
  14798. super(operations, 'shard');
  14799. this.registerCustomDirective('DimensionList', this.parseDimensionList.bind(this));
  14800. }
  14801. parseDimensionList(parser, op, attrName) {
  14802. const dimensions = [];
  14803. while (true) {
  14804. if (parser.getToken().is(_.Token.question)) {
  14805. parser.consumeToken(_.Token.question);
  14806. dimensions.push(-1);
  14807. } else if (parser.getToken().is(_.Token.integer)) {
  14808. dimensions.push(parser.parseInteger());
  14809. } else {
  14810. break;
  14811. }
  14812. if (parser.getToken().is(_.Token.bare_identifier)) {
  14813. const token = parser.getTokenSpelling().str();
  14814. if (token === 'x') {
  14815. parser.consumeToken(_.Token.bare_identifier);
  14816. continue;
  14817. } else if (token.startsWith('x')) {
  14818. parser.consumeToken(_.Token.bare_identifier);
  14819. const remaining = token.substring(1);
  14820. const parts = remaining.split('x');
  14821. for (const part of parts) {
  14822. if (part === '?') {
  14823. dimensions.push(-1);
  14824. } else if (part !== '') {
  14825. const num = parseInt(part, 10);
  14826. if (!isNaN(num)) {
  14827. dimensions.push(num);
  14828. }
  14829. }
  14830. }
  14831. break;
  14832. }
  14833. break;
  14834. }
  14835. if (parser.getToken().isNot(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.question)) {
  14836. break;
  14837. }
  14838. }
  14839. if (attrName) {
  14840. op.addAttribute(attrName, dimensions);
  14841. }
  14842. }
  14843. };
  14844. _.spirv = {};
  14845. _.spirv.PointerType = class extends _.Type {
  14846. constructor(pointeeType, storageClass) {
  14847. super(null);
  14848. this.pointeeType = pointeeType;
  14849. this.storageClass = storageClass;
  14850. }
  14851. static parse(parser) {
  14852. parser.parseLess();
  14853. const pointeeType = parser.parseType();
  14854. parser.parseComma();
  14855. let storageClass = parser.parseOptionalKeyword();
  14856. if (!storageClass) {
  14857. storageClass = parser.getToken().getSpelling().str();
  14858. parser.consumeToken(_.Token.bare_identifier);
  14859. }
  14860. parser.parseGreater();
  14861. return new _.spirv.PointerType(pointeeType, storageClass);
  14862. }
  14863. toString() {
  14864. const pointeeStr = this.pointeeType?.toString ? this.pointeeType.toString() : this.pointeeType;
  14865. return `!spirv.ptr<${pointeeStr}, ${this.storageClass}>`;
  14866. }
  14867. };
  14868. _.spirv.SPIRVDialect = class extends _.Dialect {
  14869. constructor(operations) {
  14870. super(operations, 'spirv');
  14871. this.typesWithOptionalParams = new Set(['sampler', 'sampled_image', 'matrix', 'image', 'rtarray', 'ptr', 'array', 'struct', 'coopmatrix']);
  14872. this.registerCustomDirective('ImageOperands', this.parseImageOperands.bind(this));
  14873. this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));
  14874. this.registerCustomDirective('SPIRV_I32_1DArmTensor', this.parseSPIRV_I32_1DArmTensor.bind(this));
  14875. this.registerCustomAttribute('SPIRV_ScopeAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14876. this.registerCustomAttribute('SPIRV_MemorySemanticsAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14877. this.registerCustomAttribute('SPIRV_MemoryAccessAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14878. this.registerCustomAttribute('SPIRV_GroupOperationAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14879. this.registerCustomAttribute('SPIRV_KHR_CooperativeMatrixLayoutAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14880. this.registerCustomAttribute('SPIRV_KHR_CooperativeMatrixOperandsAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14881. this.registerCustomAttribute('SPIRV_TosaExtNaNPropagationModeAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  14882. }
  14883. parseSwitchOpCases(parser, result) {
  14884. if (!parser.parseOptionalKeyword('default')) {
  14885. return;
  14886. }
  14887. if (!parser.parseOptionalColon()) {
  14888. return;
  14889. }
  14890. if (parser.getToken().isNot(_.Token.caret_identifier)) {
  14891. return;
  14892. }
  14893. const defaultDestination = parser.getToken().getSpelling().str();
  14894. parser.consumeToken(_.Token.caret_identifier);
  14895. const defaultDest = { label: defaultDestination, arguments: [] };
  14896. if (parser.parseOptionalLParen()) {
  14897. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  14898. const value = parser.parseOperand();
  14899. defaultDest.arguments.push({ value });
  14900. if (!parser.parseOptionalComma()) {
  14901. break;
  14902. }
  14903. }
  14904. if (parser.parseOptionalColon()) {
  14905. let idx = 0;
  14906. while (idx < defaultDest.arguments.length && parser.getToken().isNot(_.Token.r_paren)) {
  14907. const type = parser.parseType();
  14908. if (defaultDest.arguments[idx]) {
  14909. defaultDest.arguments[idx].type = type;
  14910. }
  14911. idx++;
  14912. parser.parseOptionalComma();
  14913. }
  14914. }
  14915. parser.parseOptionalRParen();
  14916. }
  14917. result.successors = result.successors || [];
  14918. result.successors.push(defaultDest);
  14919. const caseValues = [];
  14920. while (parser.parseOptionalComma()) {
  14921. if (parser.getToken().isNot(_.Token.integer) && parser.getToken().isNot(_.Token.minus)) {
  14922. break;
  14923. }
  14924. const value = parser.parseInteger();
  14925. caseValues.push(value);
  14926. if (!parser.parseOptionalColon()) {
  14927. break;
  14928. }
  14929. if (parser.getToken().isNot(_.Token.caret_identifier)) {
  14930. break;
  14931. }
  14932. const caseDestination = parser.getToken().getSpelling().str();
  14933. parser.consumeToken(_.Token.caret_identifier);
  14934. const caseDest = { label: caseDestination, arguments: [] };
  14935. if (parser.parseOptionalLParen()) {
  14936. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  14937. const argValue = parser.parseOperand();
  14938. caseDest.arguments.push({ value: argValue });
  14939. if (!parser.parseOptionalComma()) {
  14940. break;
  14941. }
  14942. }
  14943. if (parser.parseOptionalColon()) {
  14944. let idx = 0;
  14945. while (idx < caseDest.arguments.length && parser.getToken().isNot(_.Token.r_paren)) {
  14946. const type = parser.parseType();
  14947. if (caseDest.arguments[idx]) {
  14948. caseDest.arguments[idx].type = type;
  14949. }
  14950. idx++;
  14951. parser.parseOptionalComma();
  14952. }
  14953. }
  14954. parser.parseOptionalRParen();
  14955. }
  14956. result.successors.push(caseDest);
  14957. }
  14958. if (caseValues.length > 0) {
  14959. result.addAttribute('literals', caseValues);
  14960. }
  14961. }
  14962. parseImageOperands(parser /*, op, args */) {
  14963. if (parser.getToken().is(_.Token.l_square)) {
  14964. parser.skip('[');
  14965. }
  14966. }
  14967. parseType(parser, dialect) {
  14968. let mnemonic = parser.parseOptionalKeyword();
  14969. if (mnemonic) {
  14970. if (mnemonic === 'ptr' && parser.getToken().is(_.Token.less)) {
  14971. return _.spirv.PointerType.parse(parser);
  14972. }
  14973. // Handle sub-dialect types like arm.tensor, KHR.CooperativeMatrix, etc.
  14974. while (parser.consumeIf('.')) {
  14975. const subType = parser.parseOptionalKeyword();
  14976. if (subType) {
  14977. mnemonic += `.${subType}`;
  14978. } else {
  14979. break;
  14980. }
  14981. }
  14982. let type = `!${dialect}.${mnemonic}`;
  14983. if (parser.getToken().is(_.Token.less)) {
  14984. const content = parser.skip('<');
  14985. type += content;
  14986. }
  14987. return new _.Type(type);
  14988. }
  14989. return null;
  14990. }
  14991. parseOperation(parser, result) {
  14992. // spv.Constant value : type
  14993. if (result.op === 'spirv.Constant' || result.op === 'spv.Constant') {
  14994. const value = parser.parseAttribute();
  14995. result.addAttribute('value', value);
  14996. if (parser.parseOptionalColon()) {
  14997. const type = parser.parseType();
  14998. result.addTypes([type]);
  14999. } else if (value && value.type) {
  15000. result.addTypes([value.type]);
  15001. }
  15002. return true;
  15003. }
  15004. // SPIR-V comparison operations: result is i1 (or vector<Nxi1> for vector operands)
  15005. const spirvCompareOps = new Set([
  15006. 'spirv.SLessThan', 'spv.SLessThan',
  15007. 'spirv.SLessThanEqual', 'spv.SLessThanEqual',
  15008. 'spirv.SGreaterThan', 'spv.SGreaterThan',
  15009. 'spirv.SGreaterThanEqual', 'spv.SGreaterThanEqual',
  15010. 'spirv.ULessThan', 'spv.ULessThan',
  15011. 'spirv.ULessThanEqual', 'spv.ULessThanEqual',
  15012. 'spirv.UGreaterThan', 'spv.UGreaterThan',
  15013. 'spirv.UGreaterThanEqual', 'spv.UGreaterThanEqual',
  15014. 'spirv.IEqual', 'spv.IEqual',
  15015. 'spirv.INotEqual', 'spv.INotEqual',
  15016. 'spirv.FOrdEqual', 'spv.FOrdEqual',
  15017. 'spirv.FOrdNotEqual', 'spv.FOrdNotEqual',
  15018. 'spirv.FOrdLessThan', 'spv.FOrdLessThan',
  15019. 'spirv.FOrdLessThanEqual', 'spv.FOrdLessThanEqual',
  15020. 'spirv.FOrdGreaterThan', 'spv.FOrdGreaterThan',
  15021. 'spirv.FOrdGreaterThanEqual', 'spv.FOrdGreaterThanEqual',
  15022. 'spirv.FUnordEqual', 'spv.FUnordEqual',
  15023. 'spirv.FUnordNotEqual', 'spv.FUnordNotEqual',
  15024. 'spirv.FUnordLessThan', 'spv.FUnordLessThan',
  15025. 'spirv.FUnordLessThanEqual', 'spv.FUnordLessThanEqual',
  15026. 'spirv.FUnordGreaterThan', 'spv.FUnordGreaterThan',
  15027. 'spirv.FUnordGreaterThanEqual', 'spv.FUnordGreaterThanEqual'
  15028. ]);
  15029. if (spirvCompareOps.has(result.op)) {
  15030. const unresolvedOperands = parser.parseOperandList();
  15031. if (parser.parseOptionalColon()) {
  15032. const operandType = parser.parseType();
  15033. parser.resolveOperands(unresolvedOperands, [operandType, operandType], result.operands);
  15034. // Result type is i1 for scalar, vector<Nxi1> for vector
  15035. if (operandType instanceof _.VectorType) {
  15036. result.addTypes([new _.VectorType(operandType.shape, new _.IntegerType('i1'), operandType.scalableDims)]);
  15037. } else {
  15038. result.addTypes([new _.IntegerType('i1')]);
  15039. }
  15040. } else {
  15041. parser.resolveOperands(unresolvedOperands, [null, null], result.operands);
  15042. result.addTypes([new _.IntegerType('i1')]);
  15043. }
  15044. parser.parseOptionalAttrDict(result.attributes);
  15045. return true;
  15046. }
  15047. // Operations with '->' in their assembly format should use assembly format parsing
  15048. const arrowFormatOps = new Set([
  15049. 'spirv.GL.Distance', 'spirv.GL.FMix', 'spirv.GL.FrexpStruct', 'spirv.GL.Ldexp',
  15050. 'spirv.GL.Length', 'spirv.GL.PackHalf2x16', 'spirv.GL.UnpackHalf2x16',
  15051. 'spirv.GL.PackSnorm4x8', 'spirv.GL.UnpackSnorm4x8',
  15052. 'spirv.GLSL.Distance', 'spirv.GLSL.FMix', 'spirv.GLSL.FrexpStruct', 'spirv.GLSL.Ldexp',
  15053. 'spirv.GLSL.Length', 'spirv.GLSL.PackHalf2x16', 'spirv.GLSL.UnpackHalf2x16',
  15054. 'spirv.GLSL.PackSnorm4x8', 'spirv.GLSL.UnpackSnorm4x8',
  15055. 'spv.GL.Distance', 'spv.GL.FMix', 'spv.GL.FrexpStruct', 'spv.GL.Ldexp',
  15056. 'spv.GL.Length', 'spv.GL.PackHalf2x16', 'spv.GL.UnpackHalf2x16',
  15057. 'spv.GL.PackSnorm4x8', 'spv.GL.UnpackSnorm4x8',
  15058. 'spv.GLSL.Distance', 'spv.GLSL.FMix', 'spv.GLSL.FrexpStruct', 'spv.GLSL.Ldexp',
  15059. 'spv.GLSL.Length', 'spv.GLSL.PackHalf2x16', 'spv.GLSL.UnpackHalf2x16',
  15060. 'spv.GLSL.PackSnorm4x8', 'spv.GLSL.UnpackSnorm4x8'
  15061. ]);
  15062. if ((result.op.startsWith('spirv.GLSL.') || result.op.startsWith('spv.GLSL.') || result.op.startsWith('spirv.GL.') || result.op.startsWith('spv.GL.')) && !arrowFormatOps.has(result.op)) {
  15063. const unresolvedOperands = [];
  15064. while (parser.getToken().isNot(_.Token.colon)) {
  15065. unresolvedOperands.push(parser.parseOperand());
  15066. if (!parser.parseOptionalComma()) {
  15067. break;
  15068. }
  15069. }
  15070. if (parser.parseOptionalColon()) {
  15071. const type = parser.parseType();
  15072. for (const unresolvedOp of unresolvedOperands) {
  15073. parser.resolveOperand(unresolvedOp, type, result.operands);
  15074. }
  15075. result.types.push(type);
  15076. } else {
  15077. for (const unresolvedOp of unresolvedOperands) {
  15078. parser.resolveOperand(unresolvedOp, null, result.operands);
  15079. }
  15080. }
  15081. return true;
  15082. }
  15083. if (result.op === 'spirv.SpecConstantComposite' || result.op === 'spv.SpecConstantComposite') {
  15084. parser.parseSymbolName('sym_name', result.attributes);
  15085. parser.parseLParen();
  15086. const constituents = [];
  15087. while (parser.getToken().isNot(_.Token.r_paren)) {
  15088. if (parser.getToken().is(_.Token.at_identifier)) {
  15089. constituents.push(parser.getToken().getSpelling().str());
  15090. parser.consumeToken(_.Token.at_identifier);
  15091. }
  15092. if (!parser.parseOptionalComma()) {
  15093. break;
  15094. }
  15095. }
  15096. parser.parseRParen();
  15097. result.addAttribute('constituents', constituents);
  15098. if (parser.parseOptionalColon()) {
  15099. const type = parser.parseType();
  15100. result.addAttribute('type', type.toString());
  15101. }
  15102. return true;
  15103. }
  15104. if (result.op.endsWith('.SpecConstantCompositeReplicate')) {
  15105. parser.parseSymbolName('sym_name', result.attributes);
  15106. parser.parseLParen();
  15107. if (parser.getToken().is(_.Token.at_identifier)) {
  15108. const constituent = parser.getToken().getSpelling().str();
  15109. parser.consumeToken(_.Token.at_identifier);
  15110. result.addAttribute('constituent', constituent);
  15111. }
  15112. parser.parseRParen();
  15113. if (parser.parseOptionalColon()) {
  15114. const type = parser.parseType();
  15115. result.addAttribute('type', type.toString());
  15116. }
  15117. return true;
  15118. }
  15119. if (result.op === 'spirv.SpecConstantOperation' || result.op === 'spv.SpecConstantOperation') {
  15120. parser.parseKeyword('wraps');
  15121. const wrappedOp = parser.parseGenericOperation();
  15122. if (wrappedOp) {
  15123. const region = { blocks: [{ operations: [wrappedOp] }] };
  15124. result.regions.push(region);
  15125. if (wrappedOp.results && wrappedOp.results.length > 0) {
  15126. result.addTypes([wrappedOp.results[0].type]);
  15127. }
  15128. }
  15129. parser.parseOptionalAttrDict(result.attributes);
  15130. return true;
  15131. }
  15132. if (result.op === 'spirv.Constant' || result.op === 'spv.Constant') {
  15133. const value = parser.parseAttribute();
  15134. if (parser.parseOptionalColon()) {
  15135. const valueType = parser.parseType();
  15136. result.addAttribute('value', { ...value, valueType });
  15137. } else {
  15138. result.addAttribute('value', value);
  15139. }
  15140. if (parser.parseOptionalColon()) {
  15141. const type = parser.parseType();
  15142. result.addTypes([type]);
  15143. }
  15144. return true;
  15145. }
  15146. if (result.op === 'spirv.Load' || result.op === 'spv.Load') {
  15147. const storageClass = parser.getToken().getSpelling().str();
  15148. parser.consumeToken(_.Token.string);
  15149. result.addAttribute('storage_class', storageClass);
  15150. const ptrOperand = parser.parseOperand();
  15151. if (parser.parseOptionalLSquare()) {
  15152. const memoryAccess = [];
  15153. while (parser.getToken().isNot(_.Token.r_square)) {
  15154. if (parser.getToken().is(_.Token.string)) {
  15155. memoryAccess.push(parser.getToken().getSpelling().str());
  15156. parser.consumeToken(_.Token.string);
  15157. } else if (parser.getToken().is(_.Token.integer)) {
  15158. memoryAccess.push(parser.getToken().getSpelling().str());
  15159. parser.consumeToken(_.Token.integer);
  15160. } else {
  15161. break;
  15162. }
  15163. parser.parseOptionalComma();
  15164. }
  15165. parser.parseRSquare();
  15166. if (memoryAccess.length > 0) {
  15167. result.addAttribute('memory_access', memoryAccess.join(', '));
  15168. }
  15169. }
  15170. if (parser.parseOptionalColon()) {
  15171. const type = parser.parseType();
  15172. parser.resolveOperand(ptrOperand, null, result.operands);
  15173. result.types.push(type);
  15174. } else {
  15175. parser.resolveOperand(ptrOperand, null, result.operands);
  15176. }
  15177. return true;
  15178. }
  15179. if (result.op === 'spirv.CompositeExtract' || result.op === 'spv.CompositeExtract') {
  15180. const compositeOperand = parser.parseOperand();
  15181. if (parser.parseOptionalLSquare()) {
  15182. const indices = [];
  15183. while (parser.getToken().isNot(_.Token.r_square)) {
  15184. if (parser.getToken().is(_.Token.integer)) {
  15185. indices.push(parser.parseInteger());
  15186. }
  15187. if (parser.parseOptionalColon()) {
  15188. parser.parseType();
  15189. }
  15190. if (!parser.parseOptionalComma()) {
  15191. break;
  15192. }
  15193. }
  15194. parser.parseRSquare();
  15195. result.addAttribute('indices', indices);
  15196. }
  15197. if (parser.parseOptionalColon()) {
  15198. const type = parser.parseType();
  15199. parser.resolveOperand(compositeOperand, null, result.operands);
  15200. result.types.push(type);
  15201. } else {
  15202. parser.resolveOperand(compositeOperand, null, result.operands);
  15203. }
  15204. return true;
  15205. }
  15206. // Handle AccessChain with old syntax (no -> for result type)
  15207. // Uses compatibility flag because assemblyFormat includes `->` which is not present in old files
  15208. if (result.op === 'spirv.AccessChain' || result.op === 'spv.AccessChain') {
  15209. result.compatibility = true;
  15210. const unresolvedOperands = [];
  15211. unresolvedOperands.push(parser.parseOperand());
  15212. if (parser.parseOptionalLSquare()) {
  15213. while (parser.getToken().isNot(_.Token.r_square)) {
  15214. unresolvedOperands.push(parser.parseOperand());
  15215. if (!parser.parseOptionalComma()) {
  15216. break;
  15217. }
  15218. }
  15219. parser.parseRSquare();
  15220. }
  15221. parser.parseOptionalAttrDict(result.attributes);
  15222. if (parser.parseOptionalColon()) {
  15223. const basePtrType = parser.parseType();
  15224. const types = [basePtrType];
  15225. while (parser.parseOptionalComma()) {
  15226. types.push(parser.parseType());
  15227. }
  15228. parser.resolveOperands(unresolvedOperands, types, result.operands);
  15229. // Check for optional -> result_type (newer syntax)
  15230. if (parser.parseOptionalArrow()) {
  15231. const resultType = parser.parseType();
  15232. result.addTypes([resultType]);
  15233. } else {
  15234. // Old syntax without explicit result type - use base pointer type as fallback
  15235. // (In SPIR-V, AccessChain result is a pointer to a sub-element, but
  15236. // for visualization purposes the base ptr type is sufficient)
  15237. result.addTypes([basePtrType]);
  15238. }
  15239. } else {
  15240. for (const unresolvedOp of unresolvedOperands) {
  15241. parser.resolveOperand(unresolvedOp, null, result.operands);
  15242. }
  15243. }
  15244. return true;
  15245. }
  15246. if (result.op === 'spirv.Variable' || result.op === 'spv.Variable') {
  15247. let unresolvedInit = null;
  15248. if (parser.parseOptionalKeyword('init')) {
  15249. parser.parseLParen();
  15250. unresolvedInit = parser.parseOperand();
  15251. parser.parseRParen();
  15252. }
  15253. if (parser.getToken().is(_.Token.l_brace)) {
  15254. parser.parseAttributeDict(result.attributes);
  15255. }
  15256. if (parser.parseOptionalColon()) {
  15257. const type = parser.parseType();
  15258. result.addTypes([type]);
  15259. if (unresolvedInit) {
  15260. // The init value type should match the element type of the pointer result
  15261. parser.resolveOperand(unresolvedInit, null, result.operands);
  15262. }
  15263. } else if (unresolvedInit) {
  15264. parser.resolveOperand(unresolvedInit, null, result.operands);
  15265. }
  15266. return true;
  15267. }
  15268. if (result.op === 'spirv.Store' || result.op === 'spv.Store') {
  15269. const storageClass = parser.getToken().getSpelling().str();
  15270. parser.consumeToken(_.Token.string);
  15271. result.addAttribute('storage_class', storageClass);
  15272. const unresolvedOperands = [];
  15273. unresolvedOperands.push(parser.parseOperand());
  15274. parser.parseComma();
  15275. unresolvedOperands.push(parser.parseOperand());
  15276. if (parser.parseOptionalLSquare()) {
  15277. const memoryAccess = [];
  15278. while (parser.getToken().isNot(_.Token.r_square)) {
  15279. if (parser.getToken().is(_.Token.string)) {
  15280. memoryAccess.push(parser.getToken().getSpelling().str());
  15281. parser.consumeToken(_.Token.string);
  15282. } else if (parser.getToken().is(_.Token.integer)) {
  15283. memoryAccess.push(parser.getToken().getSpelling().str());
  15284. parser.consumeToken(_.Token.integer);
  15285. } else {
  15286. break;
  15287. }
  15288. parser.parseOptionalComma();
  15289. }
  15290. parser.parseRSquare();
  15291. if (memoryAccess.length > 0) {
  15292. result.addAttribute('memory_access', memoryAccess.join(', '));
  15293. }
  15294. }
  15295. if (parser.parseOptionalColon()) {
  15296. const type = parser.parseType();
  15297. parser.resolveOperands(unresolvedOperands, [type, type], result.operands);
  15298. } else {
  15299. for (const unresolvedOp of unresolvedOperands) {
  15300. parser.resolveOperand(unresolvedOp, null, result.operands);
  15301. }
  15302. }
  15303. return true;
  15304. }
  15305. if (result.op === 'spirv.CompositeInsert' || result.op === 'spv.CompositeInsert') {
  15306. const unresolvedOperands = [];
  15307. unresolvedOperands.push(parser.parseOperand());
  15308. parser.parseComma();
  15309. unresolvedOperands.push(parser.parseOperand());
  15310. if (parser.parseOptionalLSquare()) {
  15311. const indices = [];
  15312. while (parser.getToken().isNot(_.Token.r_square)) {
  15313. if (parser.getToken().is(_.Token.integer)) {
  15314. indices.push(parser.parseInteger());
  15315. }
  15316. if (parser.parseOptionalColon()) {
  15317. parser.parseType();
  15318. }
  15319. if (!parser.parseOptionalComma()) {
  15320. break;
  15321. }
  15322. }
  15323. parser.parseRSquare();
  15324. result.addAttribute('indices', indices);
  15325. }
  15326. if (parser.parseOptionalColon()) {
  15327. const objType = parser.parseType();
  15328. parser.resolveOperand(unresolvedOperands[0], objType, result.operands);
  15329. if (parser.parseOptionalKeyword('into')) {
  15330. const compositeType = parser.parseType();
  15331. parser.resolveOperand(unresolvedOperands[1], compositeType, result.operands);
  15332. result.types.push(compositeType);
  15333. } else {
  15334. parser.resolveOperand(unresolvedOperands[1], null, result.operands);
  15335. }
  15336. } else {
  15337. for (const unresolvedOp of unresolvedOperands) {
  15338. parser.resolveOperand(unresolvedOp, null, result.operands);
  15339. }
  15340. }
  15341. return true;
  15342. }
  15343. if (result.op === 'spirv.BranchConditional' || result.op === 'spv.BranchConditional') {
  15344. const conditionOperand = parser.parseOperand();
  15345. parser.resolveOperand(conditionOperand, null, result.operands);
  15346. // Parse optional branch weights [trueWeight, falseWeight]
  15347. if (parser.parseOptionalLSquare()) {
  15348. const weights = [];
  15349. while (parser.getToken().isNot(_.Token.r_square)) {
  15350. if (parser.getToken().is(_.Token.integer)) {
  15351. weights.push(parser.getToken().getSpelling().str());
  15352. parser.consumeToken(_.Token.integer);
  15353. }
  15354. parser.parseOptionalComma();
  15355. }
  15356. parser.parseRSquare();
  15357. if (weights.length > 0) {
  15358. result.addAttribute('branch_weights', weights);
  15359. }
  15360. }
  15361. parser.parseComma();
  15362. if (!result.successors) {
  15363. result.successors = [];
  15364. }
  15365. const trueLabel = parser.getToken().getSpelling().str();
  15366. parser.consumeToken(_.Token.caret_identifier);
  15367. const trueSucc = { label: trueLabel };
  15368. if (parser.parseOptionalLParen()) {
  15369. trueSucc.arguments = [];
  15370. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  15371. if (parser.getToken().is(_.Token.percent_identifier)) {
  15372. trueSucc.arguments.push(parser.parseOperand());
  15373. parser.parseOptionalComma();
  15374. } else {
  15375. break;
  15376. }
  15377. }
  15378. if (parser.parseOptionalColon()) {
  15379. let idx = 0;
  15380. while (parser.getToken().isNot(_.Token.r_paren) && idx < trueSucc.arguments.length) {
  15381. trueSucc.arguments[idx].type = parser.parseType();
  15382. idx++;
  15383. parser.parseOptionalComma();
  15384. }
  15385. }
  15386. parser.parseRParen();
  15387. }
  15388. result.successors.push(trueSucc);
  15389. parser.parseComma();
  15390. const falseLabel = parser.getToken().getSpelling().str();
  15391. parser.consumeToken(_.Token.caret_identifier);
  15392. const falseSucc = { label: falseLabel };
  15393. if (parser.parseOptionalLParen()) {
  15394. falseSucc.arguments = [];
  15395. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  15396. if (parser.getToken().is(_.Token.percent_identifier)) {
  15397. falseSucc.arguments.push(parser.parseOperand());
  15398. parser.parseOptionalComma();
  15399. } else {
  15400. break;
  15401. }
  15402. }
  15403. if (parser.parseOptionalColon()) {
  15404. let idx = 0;
  15405. while (parser.getToken().isNot(_.Token.r_paren) && idx < falseSucc.arguments.length) {
  15406. falseSucc.arguments[idx].type = parser.parseType();
  15407. idx++;
  15408. parser.parseOptionalComma();
  15409. }
  15410. }
  15411. parser.parseRParen();
  15412. }
  15413. result.successors.push(falseSucc);
  15414. return true;
  15415. }
  15416. if (result.op === 'spirv.CompositeConstruct' || result.op === 'spv.CompositeConstruct') {
  15417. result.compatibility = true;
  15418. const unresolvedOperands = [];
  15419. while (parser.getToken().isNot(_.Token.colon)) {
  15420. unresolvedOperands.push(parser.parseOperand());
  15421. if (!parser.parseOptionalComma()) {
  15422. break;
  15423. }
  15424. }
  15425. if (parser.parseOptionalColon()) {
  15426. if (parser.parseOptionalLParen()) {
  15427. const types = parser.parseTypeList();
  15428. parser.parseRParen();
  15429. parser.parseArrow();
  15430. parser.resolveOperands(unresolvedOperands, types, result.operands);
  15431. } else {
  15432. for (const unresolvedOp of unresolvedOperands) {
  15433. parser.resolveOperand(unresolvedOp, null, result.operands);
  15434. }
  15435. }
  15436. const type = parser.parseType();
  15437. result.types.push(type);
  15438. } else {
  15439. for (const unresolvedOp of unresolvedOperands) {
  15440. parser.resolveOperand(unresolvedOp, null, result.operands);
  15441. }
  15442. }
  15443. return true;
  15444. }
  15445. if (result.op === 'spirv.SpecConstant' || result.op === 'spv.SpecConstant') {
  15446. parser.parseSymbolName('sym_name', result.attributes);
  15447. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'spec_id') {
  15448. parser.parseKeyword('spec_id');
  15449. parser.parseLParen();
  15450. const specId = parser.parseAttribute();
  15451. result.addAttribute('spec_id', specId);
  15452. parser.parseRParen();
  15453. }
  15454. if (parser.parseOptionalEqual()) {
  15455. const defaultValue = parser.parseAttribute();
  15456. result.addAttribute('default_value', defaultValue);
  15457. }
  15458. if (parser.parseOptionalColon()) {
  15459. const type = parser.parseType();
  15460. result.addAttribute('type', type);
  15461. }
  15462. return true;
  15463. }
  15464. if (result.op === 'spirv.module' || result.op === 'spv.module') {
  15465. if (parser.getToken().is(_.Token.at_identifier)) {
  15466. parser.parseSymbolName('sym_name', result.attributes);
  15467. }
  15468. if (parser.getToken().is(_.Token.bare_identifier)) {
  15469. const addressingModel = parser.getToken().getSpelling().str();
  15470. parser.consumeToken(_.Token.bare_identifier);
  15471. result.addAttribute('addressing_model', addressingModel);
  15472. }
  15473. if (parser.getToken().is(_.Token.bare_identifier)) {
  15474. const memoryModel = parser.getToken().getSpelling().str();
  15475. parser.consumeToken(_.Token.bare_identifier);
  15476. result.addAttribute('memory_model', memoryModel);
  15477. }
  15478. if (parser.parseOptionalKeyword('requires')) {
  15479. const vce = parser.parseAttribute();
  15480. result.addAttribute('vce_triple', vce);
  15481. }
  15482. if (parser.parseOptionalKeyword('attributes')) {
  15483. parser.parseAttributeDict(result.attributes);
  15484. }
  15485. if (parser.getToken().is(_.Token.l_brace)) {
  15486. const region = result.addRegion();
  15487. parser.parseRegion(region);
  15488. }
  15489. return true;
  15490. }
  15491. if (result.op === 'spirv.ARM.Graph') {
  15492. parser.parseFunctionOp(result, false);
  15493. return true;
  15494. }
  15495. if (result.op === 'spirv.ARM.GraphEntryPoint') {
  15496. const fn = parser.getToken().getSpelling().str();
  15497. parser.consumeToken(_.Token.at_identifier);
  15498. result.addAttribute('fn', fn);
  15499. const interfaceVars = [];
  15500. while (parser.parseOptionalComma()) {
  15501. const varSymbol = parser.getToken().getSpelling().str();
  15502. parser.consumeToken(_.Token.at_identifier);
  15503. interfaceVars.push(varSymbol);
  15504. }
  15505. result.addAttribute('interface', interfaceVars);
  15506. return true;
  15507. }
  15508. if (result.op === 'spirv.func' || result.op === 'spv.func') {
  15509. if (parser.getToken().is(_.Token.at_identifier)) {
  15510. parser.parseSymbolName('sym_name', result.attributes);
  15511. }
  15512. let inputs = [];
  15513. const results = [];
  15514. const resultAttrs = [];
  15515. if (parser.getToken().is(_.Token.l_paren)) {
  15516. const argResult = parser.parseFunctionArgumentList();
  15517. inputs = argResult.arguments.map((a) => a.type);
  15518. }
  15519. if (parser.parseOptionalArrow()) {
  15520. parser.parseFunctionResultList(results, resultAttrs);
  15521. }
  15522. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  15523. if (parser.getToken().is(_.Token.string)) {
  15524. const control = parser.getToken().getSpelling().str();
  15525. parser.consumeToken(_.Token.string);
  15526. result.addAttribute('function_control', control);
  15527. }
  15528. if (parser.parseOptionalKeyword('attributes')) {
  15529. parser.parseAttributeDict(result.attributes);
  15530. }
  15531. if (parser.getToken().is(_.Token.l_brace)) {
  15532. const region = result.addRegion();
  15533. // spirv.func is IsolatedFromAbove
  15534. parser.parseRegion(region, undefined, /* isIsolatedNameScope */ true);
  15535. }
  15536. return true;
  15537. }
  15538. if (result.op === 'spirv.GlobalVariable' || result.op === 'spv.GlobalVariable') {
  15539. if (parser.getToken().is(_.Token.at_identifier)) {
  15540. parser.parseSymbolName('sym_name', result.attributes);
  15541. }
  15542. if (parser.parseOptionalKeyword('initializer')) {
  15543. parser.parseLParen();
  15544. const initSymbol = parser.getToken().getSpelling().str();
  15545. parser.consumeToken(_.Token.at_identifier);
  15546. parser.parseRParen();
  15547. result.addAttribute('initializer', initSymbol);
  15548. }
  15549. if (parser.parseOptionalKeyword('built_in')) {
  15550. parser.parseLParen();
  15551. const builtIn = parser.getToken().getSpelling().str();
  15552. parser.consumeToken(_.Token.string);
  15553. parser.parseRParen();
  15554. result.addAttribute('built_in', builtIn);
  15555. }
  15556. if (parser.parseOptionalKeyword('bind')) {
  15557. parser.parseLParen();
  15558. const binding = parser.getToken().getSpelling().str();
  15559. parser.consumeToken();
  15560. parser.parseOptionalComma();
  15561. const set = parser.getToken().getSpelling().str();
  15562. parser.consumeToken();
  15563. parser.parseRParen();
  15564. result.addAttribute('descriptor_set', set);
  15565. result.addAttribute('binding', binding);
  15566. }
  15567. if (parser.getToken().is(_.Token.l_brace)) {
  15568. parser.parseAttributeDict(result.attributes);
  15569. }
  15570. if (parser.parseOptionalColon()) {
  15571. const type = parser.parseType();
  15572. result.types = [type];
  15573. }
  15574. return true;
  15575. }
  15576. if (result.op === 'spirv.EntryPoint' || result.op === 'spv.EntryPoint') {
  15577. if (parser.getToken().is(_.Token.string)) {
  15578. const executionModel = parser.getToken().getSpelling().str();
  15579. parser.consumeToken(_.Token.string);
  15580. result.addAttribute('execution_model', executionModel);
  15581. }
  15582. result.operands = [];
  15583. while (parser.getToken().is(_.Token.at_identifier)) {
  15584. const symbol = parser.getToken().getSpelling().str();
  15585. parser.consumeToken(_.Token.at_identifier);
  15586. result.addAttribute('fn', new _.SymbolRefAttr(symbol));
  15587. parser.parseOptionalComma();
  15588. }
  15589. return true;
  15590. }
  15591. if (result.op === 'spirv.ExecutionMode' || result.op === 'spv.ExecutionMode') {
  15592. if (parser.getToken().is(_.Token.at_identifier)) {
  15593. const symbol = parser.getToken().getSpelling().str();
  15594. parser.consumeToken(_.Token.at_identifier);
  15595. result.addAttribute('fn', new _.SymbolRefAttr(symbol));
  15596. }
  15597. if (parser.getToken().is(_.Token.string)) {
  15598. const mode = parser.getToken().getSpelling().str();
  15599. parser.consumeToken(_.Token.string);
  15600. result.addAttribute('execution_mode', mode);
  15601. }
  15602. const params = [];
  15603. while (parser.parseOptionalComma()) {
  15604. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.floatliteral) || parser.getToken().is(_.Token.bare_identifier)) {
  15605. const param = parser.getToken().getSpelling().str();
  15606. parser.consumeToken();
  15607. params.push(param);
  15608. } else {
  15609. break;
  15610. }
  15611. }
  15612. if (params.length > 0) {
  15613. result.addAttribute('values', params);
  15614. }
  15615. return true;
  15616. }
  15617. if (result.op === 'spirv.mlir.loop' || result.op === 'spv.mlir.loop' || result.op === 'spirv.mlir.selection' || result.op === 'spv.mlir.selection') {
  15618. if (parser.parseOptionalKeyword('control')) {
  15619. parser.parseLParen();
  15620. const controlValue = parser.parseOptionalKeyword();
  15621. result.addAttribute('selection_control', controlValue);
  15622. parser.parseRParen();
  15623. }
  15624. result.addTypes(parser.parseOptionalArrowTypeList());
  15625. if (parser.getToken().is(_.Token.l_brace)) {
  15626. const region = result.addRegion();
  15627. parser.parseRegion(region);
  15628. }
  15629. return true;
  15630. }
  15631. // spirv.CompositeInsert with 'into' keyword
  15632. if (result.op === 'spirv.CompositeInsert' || result.op === 'spv.CompositeInsert') {
  15633. const unresolvedOperands = parser.parseOperandList();
  15634. if (parser.parseOptionalLSquare()) {
  15635. const indices = [];
  15636. while (!parser.parseOptionalRSquare()) {
  15637. const index = parser.getToken().getSpelling().str();
  15638. parser.consumeToken();
  15639. if (parser.parseOptionalColon()) {
  15640. parser.consumeToken(); // Skip type (e.g., i32)
  15641. }
  15642. indices.push(index);
  15643. parser.parseOptionalComma();
  15644. }
  15645. result.addAttribute('indices', indices);
  15646. }
  15647. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  15648. if (parser.parseOptionalKeyword('into')) {
  15649. const resultType = parser.parseType();
  15650. result.types = [resultType];
  15651. }
  15652. return true;
  15653. }
  15654. const arithmeticExtendedOps = new Set([
  15655. 'spirv.IAddCarry', 'spv.IAddCarry',
  15656. 'spirv.ISubBorrow', 'spv.ISubBorrow',
  15657. 'spirv.SMulExtended', 'spv.SMulExtended',
  15658. 'spirv.UMulExtended', 'spv.UMulExtended'
  15659. ]);
  15660. if (arithmeticExtendedOps.has(result.op)) {
  15661. parser.parseOptionalAttrDict(result.attributes);
  15662. const unresolvedOperands = parser.parseOperandList();
  15663. if (parser.parseOptionalColon()) {
  15664. const resultType = parser.parseType();
  15665. parser.resolveOperands(unresolvedOperands, [resultType, resultType], result.operands);
  15666. result.addTypes([resultType]);
  15667. } else {
  15668. for (const operand of unresolvedOperands) {
  15669. parser.resolveOperand(operand, null, result.operands);
  15670. }
  15671. }
  15672. return true;
  15673. }
  15674. if (result.op === 'spirv.INTEL.SubgroupBlockWrite' || result.op === 'spv.INTEL.SubgroupBlockWrite') {
  15675. const storageClass = parser.getToken().getSpelling().str();
  15676. parser.consumeToken(_.Token.string);
  15677. result.addAttribute('storage_class', storageClass);
  15678. const ptrUnresolved = parser.parseOperand();
  15679. parser.parseComma();
  15680. const valueUnresolved = parser.parseOperand();
  15681. let ptrType = null;
  15682. let valueType = null;
  15683. if (parser.parseOptionalColon()) {
  15684. valueType = parser.parseType();
  15685. ptrType = new _.Type(`!spirv.ptr<${valueType}, ${storageClass}>`);
  15686. }
  15687. parser.resolveOperand(ptrUnresolved, ptrType, result.operands);
  15688. parser.resolveOperand(valueUnresolved, valueType, result.operands);
  15689. return true;
  15690. }
  15691. if ((result.op === 'spirv.CopyMemory' || result.op === 'spv.CopyMemory')) {
  15692. const targetStorageClass = parser.getToken().getSpelling().str();
  15693. parser.consumeToken(_.Token.string);
  15694. result.addAttribute('target_storage_class', targetStorageClass);
  15695. const targetUnresolved = parser.parseOperand();
  15696. parser.parseComma();
  15697. const sourceStorageClass = parser.getToken().getSpelling().str();
  15698. parser.consumeToken(_.Token.string);
  15699. result.addAttribute('source_storage_class', sourceStorageClass);
  15700. const sourceUnresolved = parser.parseOperand();
  15701. if (parser.parseOptionalLSquare()) {
  15702. const memoryAccess = [];
  15703. while (parser.getToken().isNot(_.Token.r_square)) {
  15704. if (parser.getToken().is(_.Token.string)) {
  15705. memoryAccess.push(parser.getToken().getSpelling().str());
  15706. parser.consumeToken(_.Token.string);
  15707. } else if (parser.getToken().is(_.Token.integer)) {
  15708. memoryAccess.push(parser.getToken().getSpelling().str());
  15709. parser.consumeToken(_.Token.integer);
  15710. } else {
  15711. break;
  15712. }
  15713. parser.parseOptionalComma();
  15714. }
  15715. parser.parseRSquare();
  15716. if (memoryAccess.length > 0) {
  15717. result.addAttribute('memory_access', memoryAccess.join(', '));
  15718. }
  15719. }
  15720. if (parser.parseOptionalComma()) {
  15721. if (parser.parseOptionalLSquare()) {
  15722. const sourceMemoryAccess = [];
  15723. while (parser.getToken().isNot(_.Token.r_square)) {
  15724. if (parser.getToken().is(_.Token.string)) {
  15725. sourceMemoryAccess.push(parser.getToken().getSpelling().str());
  15726. parser.consumeToken(_.Token.string);
  15727. } else if (parser.getToken().is(_.Token.integer)) {
  15728. sourceMemoryAccess.push(parser.getToken().getSpelling().str());
  15729. parser.consumeToken(_.Token.integer);
  15730. } else {
  15731. break;
  15732. }
  15733. parser.parseOptionalComma();
  15734. }
  15735. parser.parseRSquare();
  15736. if (sourceMemoryAccess.length > 0) {
  15737. result.addAttribute('source_memory_access', sourceMemoryAccess.join(', '));
  15738. }
  15739. }
  15740. }
  15741. let targetType = null;
  15742. let sourceType = null;
  15743. if (parser.parseOptionalColon()) {
  15744. const elementType = parser.parseType();
  15745. targetType = new _.spirv.PointerType(elementType, targetStorageClass);
  15746. sourceType = new _.spirv.PointerType(elementType, sourceStorageClass);
  15747. }
  15748. parser.resolveOperand(targetUnresolved, targetType, result.operands);
  15749. parser.resolveOperand(sourceUnresolved, sourceType, result.operands);
  15750. return true;
  15751. }
  15752. return super.parseOperation(parser, result);
  15753. }
  15754. parseSPIRV_I32_1DArmTensor(parser, op, attrName) {
  15755. const values = [];
  15756. parser.parseLSquare();
  15757. while (parser.getToken().isNot(_.Token.r_square)) {
  15758. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus) || parser.getToken().is(_.Token.floatliteral)) {
  15759. const value = parser.parseInteger();
  15760. values.push(value);
  15761. } else {
  15762. break;
  15763. }
  15764. if (!parser.parseOptionalComma()) {
  15765. break;
  15766. }
  15767. }
  15768. parser.parseRSquare();
  15769. op.addAttribute(attrName, values);
  15770. }
  15771. };
  15772. _.WasmSSADialect = class extends _.Dialect {
  15773. constructor(operations) {
  15774. super(operations, 'wasmssa');
  15775. this.registerCustomType('WasmSSA_LocalRef', this.parseLocalRefType.bind(this));
  15776. this.registerCustomDirective('ElseRegion', this.parseElseRegion.bind(this));
  15777. this.registerCustomAttribute('WasmSSA_ValTypeAttr', this.parseValTypeAttr.bind(this));
  15778. }
  15779. parseOperation(parser, result) {
  15780. if (result.op === 'wasmssa.import_global') {
  15781. const importName = parser.getToken().getSpelling().str();
  15782. parser.consumeToken(_.Token.string);
  15783. result.addAttribute('importName', importName);
  15784. parser.parseKeyword('from');
  15785. const moduleName = parser.getToken().getSpelling().str();
  15786. parser.consumeToken(_.Token.string);
  15787. result.addAttribute('moduleName', moduleName);
  15788. parser.parseKeyword('as');
  15789. parser.parseSymbolName('sym_name', result.attributes);
  15790. if (parser.parseOptionalKeyword('mutable')) {
  15791. result.addAttribute('isMutable', new _.UnitAttr());
  15792. }
  15793. parser.parseColon();
  15794. const type = parser.parseType();
  15795. result.addAttribute('type', type);
  15796. return true;
  15797. }
  15798. if (result.op === 'wasmssa.global') {
  15799. if (parser.parseOptionalKeyword('exported')) {
  15800. result.addAttribute('exported', new _.UnitAttr());
  15801. }
  15802. parser.parseSymbolName('sym_name', result.attributes);
  15803. const type = parser.parseType();
  15804. result.addAttribute('type', type);
  15805. if (parser.parseOptionalKeyword('mutable')) {
  15806. result.addAttribute('isMutable', new _.UnitAttr());
  15807. }
  15808. parser.parseColon();
  15809. const region = result.addRegion();
  15810. parser.parseRegion(region);
  15811. return true;
  15812. }
  15813. if (result.op === 'wasmssa.func') {
  15814. if (parser.parseOptionalKeyword('exported')) {
  15815. result.addAttribute('exported', new _.UnitAttr());
  15816. }
  15817. parser.parseFunctionOp(result, false);
  15818. return true;
  15819. }
  15820. return super.parseOperation(parser, result);
  15821. }
  15822. parseType(parser) {
  15823. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'local') {
  15824. parser.parseKeyword('local');
  15825. parser.parseKeyword('ref');
  15826. parser.parseKeyword('to');
  15827. const elementType = parser.parseType();
  15828. return new _.Type(`!wasmssa<local ref to ${elementType}>`);
  15829. }
  15830. return null;
  15831. }
  15832. parseLocalRefType(parser) {
  15833. parser.parseKeyword('ref');
  15834. parser.parseKeyword('to');
  15835. const elementType = parser.parseType();
  15836. return new _.Type(`ref to ${elementType}`);
  15837. }
  15838. parseElseRegion(parser, result) {
  15839. if (parser.parseOptionalKeyword('else')) {
  15840. const region = result.addRegion();
  15841. parser.parseRegion(region);
  15842. }
  15843. }
  15844. inferResultTypes(op, vars) {
  15845. if (op.op === 'wasmssa.local') {
  15846. const typeAttr = op.attributes.get('type');
  15847. if (typeAttr) {
  15848. const elementType = typeAttr.type ? typeAttr.type : typeAttr;
  15849. op.addTypes([new _.Type(`!wasmssa<local ref to ${elementType}>`)]);
  15850. return;
  15851. }
  15852. }
  15853. if (op.op === 'wasmssa.local_get') {
  15854. const localVarEntry = vars.get('localVar');
  15855. if (localVarEntry && localVarEntry.types && localVarEntry.types.length > 0) {
  15856. const localRefType = localVarEntry.types[0];
  15857. if (localRefType) {
  15858. const typeStr = localRefType.toString();
  15859. const match = typeStr.match(/ref\s+to\s+(.+)/);
  15860. if (match) {
  15861. op.addTypes([new _.Type(match[1])]);
  15862. return;
  15863. }
  15864. }
  15865. }
  15866. }
  15867. super.inferResultTypes(op, vars);
  15868. }
  15869. parseValTypeAttr(parser) {
  15870. const type = parser.parseType();
  15871. return new _.TypeAttrOf(type);
  15872. }
  15873. };
  15874. _.CFDialect = class extends _.Dialect {
  15875. constructor(operations) {
  15876. super(operations, 'cf');
  15877. this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));
  15878. }
  15879. parseSwitchOpCases(parser, result) {
  15880. if (!parser.parseOptionalKeyword('default')) {
  15881. return false;
  15882. }
  15883. if (!parser.parseOptionalColon()) {
  15884. return false;
  15885. }
  15886. if (parser.getToken().isNot(_.Token.caret_identifier)) {
  15887. return false;
  15888. }
  15889. const defaultDestination = parser.getToken().getSpelling().str();
  15890. parser.consumeToken(_.Token.caret_identifier);
  15891. const defaultDest = { label: defaultDestination, arguments: [] };
  15892. if (parser.parseOptionalLParen()) {
  15893. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  15894. const value = parser.parseOperand();
  15895. defaultDest.arguments.push({ value });
  15896. if (!parser.parseOptionalComma()) {
  15897. break;
  15898. }
  15899. }
  15900. if (parser.parseOptionalColon()) {
  15901. let idx = 0;
  15902. while (idx < defaultDest.arguments.length && parser.getToken().isNot(_.Token.r_paren)) {
  15903. const type = parser.parseType();
  15904. if (defaultDest.arguments[idx]) {
  15905. defaultDest.arguments[idx].type = type;
  15906. }
  15907. idx++;
  15908. parser.parseOptionalComma();
  15909. }
  15910. }
  15911. parser.parseOptionalRParen();
  15912. }
  15913. result.successors = result.successors || [];
  15914. result.successors.push(defaultDest);
  15915. const caseValues = [];
  15916. const caseOperandSegments = [defaultDest.arguments.length];
  15917. while (parser.parseOptionalComma()) {
  15918. const value = parser.parseOptionalInteger();
  15919. if (value === null) {
  15920. break;
  15921. }
  15922. caseValues.push(value);
  15923. if (!parser.parseOptionalColon()) {
  15924. break;
  15925. }
  15926. if (parser.getToken().isNot(_.Token.caret_identifier)) {
  15927. break;
  15928. }
  15929. const caseDestination = parser.getToken().getSpelling().str();
  15930. parser.consumeToken(_.Token.caret_identifier);
  15931. const caseDest = { label: caseDestination, arguments: [] };
  15932. if (parser.parseOptionalLParen()) {
  15933. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  15934. const operandValue = parser.parseOperand();
  15935. caseDest.arguments.push({ value: operandValue });
  15936. if (!parser.parseOptionalComma()) {
  15937. break;
  15938. }
  15939. }
  15940. if (parser.parseOptionalColon()) {
  15941. let idx = 0;
  15942. while (idx < caseDest.arguments.length && parser.getToken().isNot(_.Token.r_paren)) {
  15943. const type = parser.parseType();
  15944. if (caseDest.arguments[idx]) {
  15945. caseDest.arguments[idx].type = type;
  15946. }
  15947. idx++;
  15948. parser.parseOptionalComma();
  15949. }
  15950. }
  15951. parser.parseOptionalRParen();
  15952. }
  15953. result.successors.push(caseDest);
  15954. caseOperandSegments.push(caseDest.arguments.length);
  15955. }
  15956. if (caseValues.length > 0) {
  15957. result.addAttribute('case_values', caseValues);
  15958. result.addAttribute('case_operand_segments', caseOperandSegments);
  15959. }
  15960. return true;
  15961. }
  15962. };
  15963. _.pdl = {};
  15964. _.pdl.ValueType = class extends _.Type {
  15965. constructor() {
  15966. super(null);
  15967. }
  15968. toString() {
  15969. return '!pdl.value';
  15970. }
  15971. };
  15972. _.pdl.TypeType = class extends _.Type {
  15973. constructor() {
  15974. super(null);
  15975. }
  15976. toString() {
  15977. return '!pdl.type';
  15978. }
  15979. };
  15980. _.pdl.AttributeType = class extends _.Type {
  15981. constructor() {
  15982. super(null);
  15983. }
  15984. toString() {
  15985. return '!pdl.attribute';
  15986. }
  15987. };
  15988. _.pdl.OperationType = class extends _.Type {
  15989. constructor() {
  15990. super(null);
  15991. }
  15992. toString() {
  15993. return '!pdl.operation';
  15994. }
  15995. };
  15996. _.pdl.RangeType = class extends _.Type {
  15997. constructor(elementType) {
  15998. super(null);
  15999. this.elementType = elementType;
  16000. }
  16001. static getElementTypeOrSelf(type) {
  16002. if (type instanceof _.pdl.RangeType) {
  16003. return type.elementType;
  16004. }
  16005. return type;
  16006. }
  16007. toString() {
  16008. const elementStr = this.elementType?.toString() || '';
  16009. const match = elementStr.match(/^!pdl\.(.+)$/);
  16010. return `!pdl.range<${match ? match[1] : elementStr}>`;
  16011. }
  16012. };
  16013. _.pdl.PDLDialect = class extends _.Dialect {
  16014. constructor(operations) {
  16015. super(operations, 'pdl');
  16016. this.registerCustomDirective('OperationOpAttributes', this.parseOperationOpAttributes.bind(this));
  16017. this.registerCustomDirective('RangeType', this.parseRangeType.bind(this));
  16018. this.registerCustomDirective('ResultsValueType', this.parseResultsValueType.bind(this));
  16019. }
  16020. parseOperation(parser, result) {
  16021. if (result.op === 'pdl.operation') {
  16022. result.compatibility = true;
  16023. return this.parseOperationOp(parser, result);
  16024. }
  16025. return super.parseOperation(parser, result);
  16026. }
  16027. parseOperationOp(parser, result) {
  16028. if (parser.getToken().is(_.Token.string)) {
  16029. const opNameValue = parser.getToken().getSpelling().str();
  16030. parser.consumeToken(_.Token.string);
  16031. result.addAttribute('opName', opNameValue);
  16032. }
  16033. if (parser.parseOptionalLParen()) {
  16034. const unresolvedOperands = [];
  16035. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  16036. unresolvedOperands.push(parser.parseOperand());
  16037. if (!parser.parseOptionalComma()) {
  16038. break;
  16039. }
  16040. }
  16041. const types = [];
  16042. if (parser.parseOptionalColon()) {
  16043. while (parser.getToken().isNot(_.Token.r_paren)) {
  16044. types.push(parser.parseType());
  16045. parser.parseOptionalComma();
  16046. }
  16047. }
  16048. for (let i = 0; i < unresolvedOperands.length; i++) {
  16049. parser.resolveOperand(unresolvedOperands[i], types[i] || null, result.operands);
  16050. }
  16051. parser.parseOptionalRParen();
  16052. }
  16053. this.parseOperationOpAttributes(parser, result);
  16054. if (parser.parseOptionalArrow()) {
  16055. parser.parseOptionalLParen();
  16056. const unresolvedTypeValues = [];
  16057. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace) && !(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'loc')) {
  16058. unresolvedTypeValues.push(parser.parseOperand());
  16059. if (!parser.parseOptionalComma()) {
  16060. break;
  16061. }
  16062. }
  16063. const types = [];
  16064. if (parser.parseOptionalColon()) {
  16065. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.l_brace) && !(parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'loc')) {
  16066. types.push(parser.parseType());
  16067. parser.parseOptionalComma();
  16068. }
  16069. }
  16070. for (let i = 0; i < unresolvedTypeValues.length; i++) {
  16071. parser.resolveOperand(unresolvedTypeValues[i], types[i] || null, result.operands);
  16072. }
  16073. parser.parseOptionalRParen();
  16074. }
  16075. result.addTypes([new _.Type('!pdl.operation')]);
  16076. return true;
  16077. }
  16078. parseOperationOpAttributes(parser, result) {
  16079. if (!parser.parseOptionalLBrace()) {
  16080. return true;
  16081. }
  16082. const attributeNames = [];
  16083. while (parser.getToken().isNot(_.Token.r_brace)) {
  16084. const name = parser.parseAttribute();
  16085. if (!parser.parseOptionalEqual()) {
  16086. break;
  16087. }
  16088. const unresolvedValue = parser.parseOperand();
  16089. parser.resolveOperand(unresolvedValue, null, result.operands);
  16090. attributeNames.push(name);
  16091. if (!parser.parseOptionalComma()) {
  16092. break;
  16093. }
  16094. }
  16095. parser.parseOptionalRBrace();
  16096. if (attributeNames.length > 0) {
  16097. result.addAttribute('attributeValueNames', attributeNames);
  16098. }
  16099. return true;
  16100. }
  16101. parseRangeType(parser, op, argumentTypes, resultTypes) {
  16102. if (argumentTypes && argumentTypes.length > 0) {
  16103. const elementType = _.pdl.RangeType.getElementTypeOrSelf(argumentTypes[0]);
  16104. resultTypes.push(new _.pdl.RangeType(elementType));
  16105. return true;
  16106. }
  16107. if (parser.parseOptionalColon()) {
  16108. const type = parser.parseType();
  16109. resultTypes.push(type);
  16110. }
  16111. return true;
  16112. }
  16113. parseResultsValueType(parser, result) {
  16114. // Parses `-> type` for pdl.results operation
  16115. // If index is present, type can be !pdl.value or !pdl.range<value>
  16116. // If index is absent, type is always !pdl.range<value> (full result range)
  16117. if (parser.parseOptionalArrow()) {
  16118. const type = parser.parseType();
  16119. result.addTypes([type]);
  16120. } else {
  16121. // Default to !pdl.range<value> when no explicit type is given
  16122. result.addTypes([new _.Type('!pdl.range<!pdl.value>')]);
  16123. }
  16124. return true;
  16125. }
  16126. };
  16127. _.PDLInterpDialect = class extends _.Dialect {
  16128. constructor(operations) {
  16129. super(operations, 'pdl_interp');
  16130. this.registerCustomDirective('CreateOperationOpAttributes', this.parseCreateOperationOpAttributes.bind(this));
  16131. this.registerCustomDirective('CreateOperationOpResults', this.parseCreateOperationOpResults.bind(this));
  16132. this.registerCustomDirective('RangeType', this.parseRangeType.bind(this));
  16133. }
  16134. parseOperation(parser, result) {
  16135. if (result.op === 'pdl_interp.func') {
  16136. parser.parseFunctionOp(result, false);
  16137. return true;
  16138. }
  16139. if (result.op === 'pdl_interp.foreach') {
  16140. return this.parseForeachOp(parser, result);
  16141. }
  16142. return super.parseOperation(parser, result);
  16143. }
  16144. parseForeachOp(parser, result) {
  16145. const loopVar = parser.parseOperand();
  16146. parser.parseColon();
  16147. const loopVarType = parser.parseType();
  16148. parser.parseKeyword('in');
  16149. const range = parser.parseOperand();
  16150. parser.resolveOperand(range, null, result.operands);
  16151. if (parser.getToken().is(_.Token.l_brace)) {
  16152. const region = {};
  16153. parser.parseRegion(region);
  16154. if (region.blocks && region.blocks.length > 0) {
  16155. if (!region.blocks[0].arguments) {
  16156. region.blocks[0].arguments = [];
  16157. }
  16158. region.blocks[0].arguments.push({ value: loopVar, type: loopVarType });
  16159. }
  16160. result.regions.push(region);
  16161. }
  16162. if (parser.parseOptionalArrow()) {
  16163. parser.consumeToken(_.Token.caret_identifier);
  16164. }
  16165. parser.parseOptionalAttrDict(result.attributes);
  16166. return true;
  16167. }
  16168. parseCreateOperationOpAttributes(parser, result) {
  16169. const attrNames = [];
  16170. if (parser.parseOptionalLBrace()) {
  16171. while (parser.getToken().isNot(_.Token.r_brace)) {
  16172. const nameAttr = parser.parseAttribute();
  16173. parser.parseEqual();
  16174. const operand = parser.parseOperand();
  16175. parser.resolveOperand(operand, null, result.operands);
  16176. attrNames.push(nameAttr);
  16177. if (!parser.parseOptionalComma()) {
  16178. break;
  16179. }
  16180. }
  16181. parser.parseRBrace();
  16182. }
  16183. if (attrNames.length > 0) {
  16184. result.addAttribute('inputAttributeNames', attrNames);
  16185. }
  16186. }
  16187. parseCreateOperationOpResults(parser, result) {
  16188. if (!parser.parseOptionalArrow()) {
  16189. return;
  16190. }
  16191. if (parser.parseOptionalLess()) {
  16192. parser.parseKeyword('inferred');
  16193. parser.parseGreater();
  16194. result.addAttribute('inferredResultTypes', true);
  16195. return;
  16196. }
  16197. parser.parseLParen();
  16198. const unresolvedOperands = [];
  16199. const types = [];
  16200. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  16201. const operand = parser.parseOperand();
  16202. unresolvedOperands.push(operand);
  16203. if (!parser.parseOptionalComma()) {
  16204. break;
  16205. }
  16206. }
  16207. if (parser.parseOptionalColon()) {
  16208. do {
  16209. const type = parser.parseType();
  16210. types.push(type);
  16211. } while (parser.parseOptionalComma());
  16212. }
  16213. for (let i = 0; i < unresolvedOperands.length; i++) {
  16214. const type = i < types.length ? types[i] : null;
  16215. parser.resolveOperand(unresolvedOperands[i], type, result.operands);
  16216. }
  16217. parser.parseRParen();
  16218. }
  16219. parseRangeType(parser, op, argumentTypes, resultTypes) {
  16220. if (argumentTypes && argumentTypes.length > 0) {
  16221. const elementType = _.pdl.RangeType.getElementTypeOrSelf(argumentTypes[0]);
  16222. resultTypes.push(new _.pdl.RangeType(elementType));
  16223. return true;
  16224. }
  16225. if (parser.parseOptionalColon()) {
  16226. const type = parser.parseType();
  16227. resultTypes.push(type);
  16228. }
  16229. return true;
  16230. }
  16231. };
  16232. _.ptr = {};
  16233. _.ptr.PtrType = class extends _.Type {
  16234. constructor(memorySpace) {
  16235. super(null);
  16236. this.memorySpace = memorySpace;
  16237. }
  16238. toString() {
  16239. return `!ptr.ptr<${this.memorySpace}>`;
  16240. }
  16241. };
  16242. _.ptr.PtrDialect = class extends _.Dialect {
  16243. constructor(operations) {
  16244. super(operations, 'ptr');
  16245. this.registerCustomAttribute('EnumProp', this.parseEnumProp.bind(this));
  16246. this.registerCustomAttribute('Ptr_PtrDiffFlags', this.parsePtrDiffFlags.bind(this));
  16247. this.registerCustomType('Ptr_PtrType', this.parsePtrType.bind(this));
  16248. }
  16249. parseEnumProp(parser, type) {
  16250. const [innerType] = type.args;
  16251. return this.parseCustomAttributeWithFallback(parser, innerType);
  16252. }
  16253. parsePtrDiffFlags(parser, type) {
  16254. if (type.values.includes(parser.getTokenSpelling().str())) {
  16255. return this.parseEnumFlags(parser, type, '|');
  16256. }
  16257. return null;
  16258. }
  16259. parsePtrType(parser) {
  16260. if (parser.getToken().is(_.Token.less)) {
  16261. const content = parser.skip('<');
  16262. const memorySpace = content.slice(1, -1);
  16263. return new _.ptr.PtrType(memorySpace);
  16264. }
  16265. return parser.parseType();
  16266. }
  16267. inferResultTypes(op, vars) {
  16268. if (op.op === 'ptr.ptr_add' && op.operands.length >= 2) {
  16269. const baseType = op.operands[0].type;
  16270. const offsetType = op.operands[1].type;
  16271. const offsetIsShaped = offsetType instanceof _.VectorType || offsetType instanceof _.RankedTensorType;
  16272. if (!offsetIsShaped) {
  16273. if (baseType) {
  16274. op.addTypes([baseType]);
  16275. }
  16276. return;
  16277. }
  16278. const baseIsShaped = baseType instanceof _.VectorType || baseType instanceof _.RankedTensorType;
  16279. if (!baseIsShaped) {
  16280. if (offsetType instanceof _.VectorType) {
  16281. op.addTypes([new _.VectorType(offsetType.dimensions, baseType, offsetType.scalableDims)]);
  16282. } else if (offsetType instanceof _.RankedTensorType) {
  16283. op.addTypes([new _.RankedTensorType(offsetType.shape, baseType, offsetType.encoding)]);
  16284. }
  16285. return;
  16286. }
  16287. if (baseType) {
  16288. op.addTypes([baseType]);
  16289. }
  16290. return;
  16291. }
  16292. super.inferResultTypes(op, vars);
  16293. }
  16294. };
  16295. _.EmitCDialect = class extends _.Dialect {
  16296. constructor(operations) {
  16297. super(operations, 'emitc');
  16298. this.registerCustomType('EmitC_LValueType', this.parseLValueType.bind(this));
  16299. this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));
  16300. this.registerCustomDirective('EmitCGlobalOpTypeAndInitialValue', this.parseTypeAndInitialValue.bind(this));
  16301. this.registerCustomDirective('EmitCFieldOpTypeAndInitialValue', this.parseTypeAndInitialValue.bind(this));
  16302. }
  16303. parseOperation(parser, result) {
  16304. if (result.op === 'emitc.include') {
  16305. if (parser.parseOptionalLess()) {
  16306. const include = parser.getToken().getSpelling().str();
  16307. parser.consumeToken(_.Token.string);
  16308. parser.parseGreater();
  16309. result.addAttribute('is_standard_include', true);
  16310. result.addAttribute('include', include);
  16311. } else {
  16312. const include = parser.getToken().getSpelling().str();
  16313. parser.consumeToken(_.Token.string);
  16314. result.addAttribute('include', include);
  16315. }
  16316. return true;
  16317. }
  16318. if (result.op === 'emitc.func') {
  16319. parser.parseFunctionOp(result, false);
  16320. return true;
  16321. }
  16322. if (result.op === 'emitc.expression') {
  16323. while (parser.getToken().is(_.Token.percent_identifier)) {
  16324. const operand = parser.parseOperand();
  16325. parser.resolveOperand(operand, null, result.operands);
  16326. if (!parser.parseOptionalComma()) {
  16327. break;
  16328. }
  16329. }
  16330. if (parser.parseOptionalKeyword('noinline')) {
  16331. result.addAttribute('do_not_inline', true);
  16332. }
  16333. if (parser.parseOptionalColon()) {
  16334. const type = parser.parseType();
  16335. if (type instanceof _.FunctionType) {
  16336. result.addAttribute('type', type);
  16337. result.addTypes(type.results);
  16338. }
  16339. }
  16340. if (parser.getToken().is(_.Token.l_brace)) {
  16341. const region = result.addRegion();
  16342. parser.parseRegion(region);
  16343. }
  16344. return true;
  16345. }
  16346. if (result.op === 'emitc.if') {
  16347. const cond = parser.parseOperand();
  16348. parser.resolveOperand(cond, null, result.operands);
  16349. const thenRegion = {};
  16350. parser.parseRegion(thenRegion);
  16351. result.regions.push(thenRegion);
  16352. if (parser.parseOptionalKeyword('else')) {
  16353. const elseRegion = {};
  16354. parser.parseRegion(elseRegion);
  16355. result.regions.push(elseRegion);
  16356. }
  16357. parser.parseOptionalAttrDict(result.attributes);
  16358. return true;
  16359. }
  16360. if (result.op === 'emitc.do') {
  16361. const bodyRegion = {};
  16362. parser.parseRegion(bodyRegion);
  16363. result.regions.push(bodyRegion);
  16364. parser.parseKeyword('while');
  16365. const condRegion = {};
  16366. parser.parseRegion(condRegion);
  16367. result.regions.push(condRegion);
  16368. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  16369. return true;
  16370. }
  16371. if (result.op === 'emitc.for') {
  16372. const iterVar = parser.parseOperand();
  16373. parser.parseEqual();
  16374. const lb = parser.parseOperand();
  16375. parser.resolveOperand(lb, null, result.operands);
  16376. parser.parseKeyword('to');
  16377. const ub = parser.parseOperand();
  16378. parser.resolveOperand(ub, null, result.operands);
  16379. parser.parseKeyword('step');
  16380. const step = parser.parseOperand();
  16381. parser.resolveOperand(step, null, result.operands);
  16382. if (parser.parseOptionalColon()) {
  16383. const type = parser.parseType();
  16384. result.addAttribute('type', type.toString());
  16385. }
  16386. result.addAttribute('iterVar', { value: iterVar, hidden: true });
  16387. if (parser.getToken().is(_.Token.l_brace)) {
  16388. const region = result.addRegion();
  16389. parser.parseRegion(region);
  16390. }
  16391. return true;
  16392. }
  16393. return super.parseOperation(parser, result);
  16394. }
  16395. parseLValueType(parser) {
  16396. if (parser.getToken().is(_.Token.less)) {
  16397. const content = parser.skip('<');
  16398. return new _.Type(`!emitc.lvalue${content}`);
  16399. }
  16400. return null;
  16401. }
  16402. parseSwitchCases(parser, op /*, args */) {
  16403. const caseValues = [];
  16404. while (parser.parseOptionalKeyword('case')) {
  16405. const value = parser.parseInteger();
  16406. caseValues.push(value);
  16407. if (parser.getToken().is(_.Token.l_brace)) {
  16408. const region = op.addRegion();
  16409. parser.parseRegion(region);
  16410. }
  16411. }
  16412. if (caseValues.length > 0) {
  16413. op.addAttribute('cases', caseValues);
  16414. }
  16415. }
  16416. parseTypeAndInitialValue(parser, op, typeAttr = 'type', valueAttr = 'initial_value') {
  16417. const type = parser.parseType();
  16418. op.addAttribute(typeAttr, type);
  16419. if (parser.parseOptionalEqual()) {
  16420. const initialValue = parser.parseAttribute(type);
  16421. op.addAttribute(valueAttr, initialValue);
  16422. }
  16423. }
  16424. };
  16425. _.AsukaDialect = class extends _.Dialect {
  16426. constructor(operations) {
  16427. super(operations, 'asuka');
  16428. }
  16429. parseOperation(parser, result) {
  16430. // https://github.com/monellz/FlashTensor/blob/main/bench/ea.mlir
  16431. // uses batch_dims and reduce_dims not valid given the assemblyFormat spec.
  16432. // Custom parsing preserves compatibility with this file.
  16433. if (result.op === 'asuka.dot' || result.op === 'asuka.add' || result.op === 'asuka.split' || result.op === 'asuka.softmax' || result.op === 'asuka.reduce') {
  16434. result.compatibility = true;
  16435. result.operands = parser.parseOperandList();
  16436. while (parser.getToken().is(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace)) {
  16437. const attrName = parser.getToken().getSpelling().str();
  16438. parser.consumeToken(_.Token.bare_identifier);
  16439. if (parser.parseOptionalEqual()) {
  16440. let attrValue = null;
  16441. if (parser.getToken().is(_.Token.l_square)) {
  16442. attrValue = parser.parseAttribute();
  16443. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'x') {
  16444. parser.consumeToken(_.Token.bare_identifier); // consume 'x'
  16445. const secondValue = parser.parseAttribute();
  16446. attrValue = { kind: 'pair', first: attrValue, second: secondValue };
  16447. }
  16448. } else if (parser.getToken().is(_.Token.integer)) {
  16449. attrValue = parser.getToken().getSpelling().str();
  16450. parser.consumeToken(_.Token.integer);
  16451. } else {
  16452. attrValue = parser.parseAttribute();
  16453. }
  16454. result.addAttribute(attrName, attrValue);
  16455. parser.parseOptionalComma();
  16456. }
  16457. }
  16458. if (parser.parseOptionalColon()) {
  16459. const funcType = parser.parseFunctionType();
  16460. parser.resolveOperands(result.operands, funcType.inputs);
  16461. for (const resultType of funcType.results) {
  16462. result.addTypes([resultType]);
  16463. }
  16464. }
  16465. return true;
  16466. }
  16467. return super.parseOperation(parser, result);
  16468. }
  16469. };
  16470. _.async = {};
  16471. _.async.TokenType = class extends _.Type {
  16472. constructor() {
  16473. super(null);
  16474. }
  16475. toString() {
  16476. return '!async.token';
  16477. }
  16478. };
  16479. _.async.GroupType = class extends _.Type {
  16480. constructor() {
  16481. super(null);
  16482. }
  16483. toString() {
  16484. return '!async.group';
  16485. }
  16486. };
  16487. _.async.ValueType = class extends _.Type {
  16488. constructor(valueType) {
  16489. super(null);
  16490. this.valueType = valueType;
  16491. }
  16492. toString() {
  16493. const inner = this.valueType?.toString ? this.valueType.toString() : this.valueType;
  16494. return `!async.value<${inner}>`;
  16495. }
  16496. static parse(parser) {
  16497. if (parser.consumeIf(_.Token.less)) {
  16498. const innerType = parser.parseType();
  16499. parser.parseGreater();
  16500. return new _.async.ValueType(innerType);
  16501. }
  16502. return parser.parseType();
  16503. }
  16504. };
  16505. _.async.AsyncDialect = class extends _.Dialect {
  16506. constructor(operations) {
  16507. super(operations, 'async');
  16508. this.registerCustomDirective('AwaitResultType', this.parseAwaitResultType.bind(this));
  16509. this.registerCustomType('Async_ValueType', (parser) => _.async.ValueType.parse(parser));
  16510. }
  16511. parseType(parser, dialect) {
  16512. const mnemonic = parser.parseOptionalKeyword();
  16513. if (mnemonic === 'coro.handle' || mnemonic === 'coro.id' || mnemonic === 'coro.state') {
  16514. return new _.Type(`!${dialect}.${mnemonic}`);
  16515. }
  16516. if (mnemonic === 'token') {
  16517. return new _.async.TokenType();
  16518. }
  16519. if (mnemonic === 'group') {
  16520. return new _.async.GroupType();
  16521. }
  16522. if (mnemonic === 'value') {
  16523. if (parser.consumeIf(_.Token.less)) {
  16524. const innerType = parser.parseType();
  16525. parser.parseGreater();
  16526. return new _.async.ValueType(innerType);
  16527. }
  16528. return new _.async.ValueType(null);
  16529. }
  16530. throw new mlir.Error(`Unknown '${dialect}' type '${mnemonic}' ${parser.getNameLoc()}`);
  16531. }
  16532. parseOperation(parser, result) {
  16533. if (result.op === 'async.execute') {
  16534. return this.parseExecuteOp(parser, result);
  16535. }
  16536. if (result.op === 'async.func') {
  16537. return this.parseFuncOp(parser, result);
  16538. }
  16539. return super.parseOperation(parser, result);
  16540. }
  16541. parseExecuteOp(parser, result) {
  16542. const tokenArgs = parser.parseOperandList('optionalSquare');
  16543. const tokenTypes = tokenArgs.map(() => null);
  16544. parser.resolveOperands(tokenArgs, tokenTypes, result.operands);
  16545. if (parser.parseOptionalLParen()) {
  16546. while (parser.getToken().isNot(_.Token.r_paren)) {
  16547. const operand = parser.parseOperand();
  16548. if (parser.parseOptionalKeyword('as')) {
  16549. parser.parseOperand();
  16550. }
  16551. let type = null;
  16552. if (parser.parseOptionalColon()) {
  16553. type = parser.parseType();
  16554. }
  16555. parser.resolveOperand(operand, type, result.operands);
  16556. if (!parser.parseOptionalComma()) {
  16557. break;
  16558. }
  16559. }
  16560. parser.parseRParen();
  16561. }
  16562. const valueTypes = [];
  16563. if (parser.parseOptionalArrow()) {
  16564. if (parser.parseOptionalLParen()) {
  16565. while (parser.getToken().isNot(_.Token.r_paren)) {
  16566. valueTypes.push(parser.parseType());
  16567. if (!parser.parseOptionalComma()) {
  16568. break;
  16569. }
  16570. }
  16571. parser.parseRParen();
  16572. } else {
  16573. valueTypes.push(parser.parseType());
  16574. }
  16575. }
  16576. result.addTypes([new _.async.TokenType()]);
  16577. result.addTypes(valueTypes);
  16578. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  16579. if (parser.getToken().is(_.Token.l_brace)) {
  16580. const region = result.addRegion();
  16581. parser.parseRegion(region);
  16582. }
  16583. return true;
  16584. }
  16585. parseFuncOp(parser, result) {
  16586. parser.parseOptionalVisibilityKeyword(result.attributes);
  16587. parser.parseSymbolName('sym_name', result.attributes);
  16588. const argResult = parser.parseFunctionArgumentList();
  16589. const inputs = argResult.arguments.map((a) => a.type);
  16590. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  16591. const results = [];
  16592. const resultAttrs = [];
  16593. if (parser.parseOptionalArrow()) {
  16594. parser.parseFunctionResultList(results, resultAttrs);
  16595. }
  16596. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  16597. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  16598. if (parser.getToken().is(_.Token.l_brace)) {
  16599. const region = result.addRegion();
  16600. parser.parseRegion(region);
  16601. }
  16602. return true;
  16603. }
  16604. parseAwaitResultType(parser, op, operandTypeArg) {
  16605. const operandType = parser.parseType();
  16606. if (Array.isArray(operandTypeArg)) {
  16607. operandTypeArg.push(operandType);
  16608. }
  16609. if (operandType instanceof _.async.ValueType && operandType.valueType) {
  16610. op.addTypes([operandType.valueType]);
  16611. }
  16612. }
  16613. };
  16614. _.ArithDialect = class extends _.Dialect {
  16615. constructor(operations) {
  16616. super(operations, 'arith');
  16617. this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  16618. this.registerCustomAttribute('Arith_IntegerOverflowAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  16619. }
  16620. parseOperation(parser, result) {
  16621. if (result.op === 'arith.select') {
  16622. return this.parseSelectOp(parser, result);
  16623. }
  16624. return super.parseOperation(parser, result);
  16625. }
  16626. parseSelectOp(parser, result) {
  16627. const unresolvedOperands = parser.parseOperandList();
  16628. if (parser.getToken().is(_.Token.l_brace)) {
  16629. parser.parseAttributeDict(result.attributes);
  16630. }
  16631. if (parser.parseOptionalColon()) {
  16632. const condType = parser.parseType();
  16633. if (parser.parseOptionalComma()) {
  16634. const resultType = parser.parseType();
  16635. const types = [condType, resultType, resultType];
  16636. parser.resolveOperands(unresolvedOperands, types, result.operands);
  16637. if (result.types.length > 0) {
  16638. result.types[0] = resultType;
  16639. } else {
  16640. result.addTypes([resultType]);
  16641. }
  16642. } else {
  16643. const types = unresolvedOperands.map(() => condType);
  16644. parser.resolveOperands(unresolvedOperands, types, result.operands);
  16645. if (result.types.length > 0) {
  16646. result.types[0] = condType;
  16647. } else {
  16648. result.addTypes([condType]);
  16649. }
  16650. }
  16651. } else {
  16652. for (const operand of unresolvedOperands) {
  16653. parser.resolveOperand(operand, null, result.operands);
  16654. }
  16655. }
  16656. return true;
  16657. }
  16658. };
  16659. _.BuiltinDialect = class extends _.Dialect {
  16660. constructor(operations) {
  16661. super(operations, 'builtin');
  16662. this.blobManager = new Map();
  16663. }
  16664. parseOperation(parser, result) {
  16665. if (result.op === 'builtin.call' || result.op === 'builtin.call_indirect') {
  16666. parser.parseSymbolName('callee', result.attributes);
  16667. const unresolvedOperands = parser.parseOperandList();
  16668. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  16669. if (parser.parseOptionalArrow()) {
  16670. const resultTypes = parser.parseFunctionResultTypes();
  16671. result.addTypes(resultTypes);
  16672. }
  16673. return true;
  16674. }
  16675. return super.parseOperation(parser, result);
  16676. }
  16677. readType(reader) {
  16678. const typeCode = reader.readVarInt();
  16679. switch (typeCode) {
  16680. case 0: { // IntegerType
  16681. const widthAndSign = reader.readVarInt();
  16682. const width = widthAndSign >> 2;
  16683. const signedness = widthAndSign & 0x3;
  16684. if (signedness === 0) {
  16685. return new _.IntegerType(`i${width}`);
  16686. }
  16687. if (signedness === 1) {
  16688. return new _.IntegerType(`si${width}`);
  16689. }
  16690. return new _.IntegerType(`ui${width}`);
  16691. }
  16692. case 1: // IndexType
  16693. return new _.IndexType();
  16694. case 2: { // FunctionType
  16695. const numInputs = reader.readVarInt();
  16696. const inputs = [];
  16697. for (let i = 0; i < numInputs; i++) {
  16698. inputs.push(reader.readType());
  16699. }
  16700. const numResults = reader.readVarInt();
  16701. const results = [];
  16702. for (let i = 0; i < numResults; i++) {
  16703. results.push(reader.readType());
  16704. }
  16705. return new _.FunctionType(inputs, results);
  16706. }
  16707. case 3: return new _.FloatType('bf16'); // BFloat16Type
  16708. case 4: return new _.FloatType('f16'); // Float16Type
  16709. case 5: return new _.FloatType('f32'); // Float32Type
  16710. case 6: return new _.FloatType('f64'); // Float64Type
  16711. case 7: return new _.FloatType('f80'); // Float80Type
  16712. case 8: return new _.FloatType('f128'); // Float128Type
  16713. case 9: { // ComplexType
  16714. const elementType = reader.readType();
  16715. return new _.Type(`complex<${elementType.toString()}>`);
  16716. }
  16717. case 10: { // MemRefType
  16718. const shape = reader.readSignedVarInts();
  16719. const elementType = reader.readType();
  16720. reader.readAttribute(); // layout
  16721. return new _.Type(`memref<${shape.join('x')}x${elementType.toString()}>`);
  16722. }
  16723. case 11: { // MemRefTypeWithMemSpace
  16724. reader.readAttribute(); // memorySpace
  16725. const shape = reader.readSignedVarInts();
  16726. const elementType = reader.readType();
  16727. reader.readAttribute(); // layout
  16728. return new _.Type(`memref<${shape.join('x')}x${elementType.toString()}>`);
  16729. }
  16730. case 12: // NoneType
  16731. return new _.NoneType();
  16732. case 13: { // RankedTensorType
  16733. const shape = reader.readSignedVarInts();
  16734. const elementType = reader.readType();
  16735. return new _.RankedTensorType(shape, elementType, null);
  16736. }
  16737. case 14: { // RankedTensorTypeWithEncoding
  16738. const encoding = reader.readAttribute();
  16739. const shape = reader.readSignedVarInts();
  16740. const elementType = reader.readType();
  16741. return new _.RankedTensorType(shape, elementType, encoding);
  16742. }
  16743. case 15: { // TupleType
  16744. const numTypes = reader.readVarInt();
  16745. const types = [];
  16746. for (let i = 0; i < numTypes; i++) {
  16747. types.push(reader.readType());
  16748. }
  16749. return new _.Type(`tuple<${types.map((t) => t.toString()).join(', ')}>`);
  16750. }
  16751. case 16: { // UnrankedMemRefType
  16752. const elementType = reader.readType();
  16753. return new _.Type(`memref<*x${elementType.toString()}>`);
  16754. }
  16755. case 17: { // UnrankedMemRefTypeWithMemSpace
  16756. reader.readAttribute(); // memorySpace
  16757. const elementType = reader.readType();
  16758. return new _.Type(`memref<*x${elementType.toString()}>`);
  16759. }
  16760. case 18: { // UnrankedTensorType
  16761. const elementType = reader.readType();
  16762. return new _.UnrankedTensorType(elementType);
  16763. }
  16764. case 19: { // VectorType
  16765. const shape = reader.readSignedVarInts();
  16766. const elementType = reader.readType();
  16767. return new _.VectorType(shape, elementType);
  16768. }
  16769. case 20: { // VectorTypeWithScalableDims
  16770. const numScalable = reader.readVarInt();
  16771. for (let i = 0; i < numScalable; i++) {
  16772. reader.readByte(); // scalableDims flags
  16773. }
  16774. const shape = reader.readSignedVarInts();
  16775. const elementType = reader.readType();
  16776. return new _.VectorType(shape, elementType);
  16777. }
  16778. default:
  16779. throw new mlir.Error(`Unsupported built-in type code '${typeCode}'.`);
  16780. }
  16781. }
  16782. readAttribute(reader) {
  16783. const typeCode = reader.readVarInt();
  16784. switch (typeCode) {
  16785. case 0: { // ArrayAttr
  16786. const count = reader.readVarInt();
  16787. const elements = [];
  16788. for (let i = 0; i < count; i++) {
  16789. elements.push(reader.readAttribute());
  16790. }
  16791. return new _.ArrayAttr(elements);
  16792. }
  16793. case 1: { // DictionaryAttr
  16794. const count = reader.readVarInt();
  16795. const attrs = new Map();
  16796. for (let i = 0; i < count; i++) {
  16797. const nameAttr = reader.readAttribute();
  16798. const valueAttr = reader.readAttribute();
  16799. const name = nameAttr && nameAttr.value ? nameAttr.value : `attr_${i}`;
  16800. attrs.set(name, valueAttr);
  16801. }
  16802. return { name: 'dictionary', value: attrs };
  16803. }
  16804. case 2: { // StringAttr
  16805. const value = reader.readString();
  16806. return new _.StringAttr(value);
  16807. }
  16808. case 3: { // StringAttrWithType
  16809. const value = reader.readString();
  16810. const type = reader.readType();
  16811. return new _.StringAttr(value, type);
  16812. }
  16813. case 4: { // FlatSymbolRefAttr
  16814. const value = reader.readString();
  16815. return new _.SymbolRefAttr(`@${value}`);
  16816. }
  16817. case 5: { // SymbolRefAttr
  16818. const root = reader.readString();
  16819. const numNested = reader.readVarInt();
  16820. let value = `@${root}`;
  16821. for (let i = 0; i < numNested; i++) {
  16822. value += `::@${reader.readString()}`;
  16823. }
  16824. return new _.SymbolRefAttr(value);
  16825. }
  16826. case 6: { // TypeAttr
  16827. const type = reader.readType();
  16828. return new _.TypeAttrOf(type);
  16829. }
  16830. case 7: // UnitAttr
  16831. return new _.UnitAttr();
  16832. case 8: { // IntegerAttr
  16833. const getIntegerBitWidth = (type) => {
  16834. const str = type ? type.toString() : '';
  16835. const match = str.match(/^[su]?i(\d+)$/);
  16836. if (match) {
  16837. return parseInt(match[1], 10);
  16838. }
  16839. if (str === 'index') {
  16840. return 64;
  16841. }
  16842. throw new mlir.Error(`Unsupported integer type '${str}'.`);
  16843. };
  16844. const type = reader.readType();
  16845. const bitWidth = getIntegerBitWidth(type);
  16846. let value = null;
  16847. if (bitWidth <= 8) {
  16848. value = BigInt(reader.readByte());
  16849. } else if (bitWidth <= 64) {
  16850. value = reader.readSignedVarInt();
  16851. } else {
  16852. const numWords = reader.readVarInt();
  16853. value = 0n;
  16854. for (let i = 0; i < numWords; i++) {
  16855. const word = reader.readSignedVarInt();
  16856. value |= (word << BigInt(i * 64));
  16857. }
  16858. }
  16859. return new _.IntegerAttr(type, value);
  16860. }
  16861. case 9: { // FloatAttr
  16862. const type = reader.readType();
  16863. const value = reader.readAPFloatWithKnownSemantics(type);
  16864. return new _.FloatAttr(type, value);
  16865. }
  16866. case 10: { // CallSiteLoc
  16867. const caller = reader.readAttribute();
  16868. const callee = reader.readAttribute();
  16869. const callerStr = caller && caller.value ? caller.value : '<caller>';
  16870. const calleeStr = callee && callee.value ? callee.value : '<callee>';
  16871. return { name: 'loc', value: `callsite(${callerStr} at ${calleeStr})` };
  16872. }
  16873. case 11: { // FileLineColLoc
  16874. const filename = reader.readString();
  16875. const line = reader.readVarInt();
  16876. const col = reader.readVarInt();
  16877. return { name: 'loc', value: `${filename}:${line}:${col}` };
  16878. }
  16879. case 12: { // FusedLoc
  16880. const count = reader.readVarInt();
  16881. const locations = [];
  16882. for (let i = 0; i < count; i++) {
  16883. const loc = reader.readAttribute();
  16884. locations.push(loc && loc.value ? loc.value : '<loc>');
  16885. }
  16886. return { name: 'loc', value: `fused[${locations.join(', ')}]` };
  16887. }
  16888. case 13: { // FusedLocWithMetadata
  16889. const metadata = reader.readAttribute();
  16890. const count = reader.readVarInt();
  16891. const locations = [];
  16892. for (let i = 0; i < count; i++) {
  16893. const loc = reader.readAttribute();
  16894. locations.push(loc && loc.value ? loc.value : '<loc>');
  16895. }
  16896. const metaStr = metadata && metadata.value !== undefined ? metadata.value : '<meta>';
  16897. return { name: 'loc', value: `fused<${metaStr}>[${locations.join(', ')}]` };
  16898. }
  16899. case 14: { // NameLoc
  16900. const nameAttr = reader.readAttribute();
  16901. const childLoc = reader.readAttribute();
  16902. const nameStr = nameAttr && nameAttr.value !== undefined ? nameAttr.value : '<name>';
  16903. const childStr = childLoc && childLoc.value ? childLoc.value : '<loc>';
  16904. return { name: 'loc', value: `#loc(${nameStr}(${childStr}))` };
  16905. }
  16906. case 15: // UnknownLoc
  16907. return { name: 'loc', value: 'unknown' };
  16908. case 16: { // DenseResourceElementsAttr
  16909. const type = reader.readType();
  16910. const resource = reader.readResourceHandle();
  16911. const blobData = resource && resource.value && resource.value.kind === 'blob' ? resource.value.data : null;
  16912. const handle = new _.DenseResourceElementsHandle(resource ? resource.key : 'unknown', blobData);
  16913. return new _.DenseResourceElementsAttr(type, handle);
  16914. }
  16915. case 17: { // DenseArrayAttr
  16916. const type = reader.readType();
  16917. const size = reader.readVarInt();
  16918. const blob = reader.readBlob();
  16919. return new _.DenseArrayAttr(type, size, blob);
  16920. }
  16921. case 18: { // DenseIntOrFPElementsAttr
  16922. const type = reader.readType();
  16923. const blob = reader.readBlob();
  16924. return new _.DenseElementsAttr(blob, type);
  16925. }
  16926. case 19: { // DenseStringElementsAttr
  16927. const type = reader.readType();
  16928. const isSplat = reader.readVarInt() !== 0;
  16929. const count = reader.readVarInt();
  16930. const strings = [];
  16931. for (let i = 0; i < count; i++) {
  16932. strings.push(reader.readString());
  16933. }
  16934. return { name: 'dense_string', value: strings, type, isSplat };
  16935. }
  16936. case 20: { // SparseElementsAttr
  16937. const type = reader.readType();
  16938. const indices = reader.readAttribute();
  16939. const values = reader.readAttribute();
  16940. return new _.SparseElementsAttr(type, indices, values);
  16941. }
  16942. case 21: { // DistinctAttr
  16943. const referencedAttr = reader.readAttribute();
  16944. return { name: 'distinct', value: referencedAttr };
  16945. }
  16946. case 22: { // FileLineColRange
  16947. const filename = reader.readString();
  16948. const numLocs = reader.readVarInt();
  16949. const locs = [];
  16950. for (let i = 0; i < numLocs; i++) {
  16951. locs.push(reader.readVarInt());
  16952. }
  16953. return { name: 'loc', value: `${filename}:${locs.join(':')}` };
  16954. }
  16955. default:
  16956. return { name: 'builtin', value: `<builtin code ${typeCode}>` };
  16957. }
  16958. }
  16959. declareResource(key) {
  16960. if (!this.blobManager.has(key)) {
  16961. this.blobManager.set(key, new _.DenseResourceElementsHandle(key));
  16962. }
  16963. return this.blobManager.get(key);
  16964. }
  16965. getResourceKey(handle) {
  16966. return handle.key;
  16967. }
  16968. parseResource(entry) {
  16969. const blob = entry.parseAsBlob();
  16970. this.blobManager.get(entry.key).blob = blob;
  16971. }
  16972. };
  16973. _.BufferizationDialect = class extends _.Dialect {
  16974. constructor(operations) {
  16975. super(operations, 'bufferization');
  16976. }
  16977. parseOperation(parser, result) {
  16978. if (result.op === 'bufferization.alloc_tensor') {
  16979. if (!parser.parseOptionalLParen()) {
  16980. return false;
  16981. }
  16982. const unresolvedDynamicDims = [];
  16983. while (parser.getToken().isNot(_.Token.r_paren)) {
  16984. if (parser.getToken().is(_.Token.percent_identifier)) {
  16985. unresolvedDynamicDims.push(parser.parseOperand());
  16986. if (!parser.parseOptionalComma()) {
  16987. break;
  16988. }
  16989. } else {
  16990. break;
  16991. }
  16992. }
  16993. parser.parseRParen();
  16994. let unresolvedCopy = null;
  16995. if (parser.parseOptionalKeyword('copy')) {
  16996. parser.parseLParen();
  16997. unresolvedCopy = parser.parseOperand();
  16998. parser.parseRParen();
  16999. }
  17000. let unresolvedSizeHint = null;
  17001. if (parser.parseOptionalKeyword('size_hint')) {
  17002. parser.parseEqual();
  17003. unresolvedSizeHint = parser.parseOperand();
  17004. }
  17005. parser.parseOptionalAttrDict(result.attributes);
  17006. if (parser.parseOptionalColon()) {
  17007. const resultType = parser.parseType();
  17008. const indexType = new _.IndexType();
  17009. parser.resolveOperands(unresolvedDynamicDims, unresolvedDynamicDims.map(() => indexType), result.operands);
  17010. if (unresolvedCopy) {
  17011. parser.resolveOperand(unresolvedCopy, resultType, result.operands);
  17012. }
  17013. if (unresolvedSizeHint) {
  17014. parser.resolveOperand(unresolvedSizeHint, indexType, result.operands);
  17015. }
  17016. if (result.types.length === 0) {
  17017. result.types.push(resultType);
  17018. } else {
  17019. result.types[0] = resultType;
  17020. }
  17021. }
  17022. return true;
  17023. }
  17024. // bufferization.to_memref %tensor read_only : tensor_type to memref_type
  17025. if (result.op === 'bufferization.to_memref') {
  17026. let unresolvedOperand = null;
  17027. if (parser.getToken().is(_.Token.percent_identifier)) {
  17028. unresolvedOperand = parser.parseOperand();
  17029. }
  17030. if (parser.parseOptionalKeyword('read_only')) {
  17031. result.addAttribute('read_only', true);
  17032. }
  17033. parser.parseOptionalAttrDict(result.attributes);
  17034. if (parser.parseOptionalColon()) {
  17035. const sourceType = parser.parseType();
  17036. result.addAttribute('source_type', sourceType);
  17037. if (unresolvedOperand) {
  17038. parser.resolveOperand(unresolvedOperand, sourceType, result.operands);
  17039. }
  17040. parser.parseKeyword('to');
  17041. const destType = parser.parseType();
  17042. result.addTypes([destType]);
  17043. } else if (unresolvedOperand) {
  17044. parser.resolveOperand(unresolvedOperand, null, result.operands);
  17045. }
  17046. return true;
  17047. }
  17048. return super.parseOperation(parser, result);
  17049. }
  17050. inferResultTypes(op, vars) {
  17051. if (op.op === 'bufferization.dealloc') {
  17052. // DeallocOp::inferReturnTypes - one i1 per retained memref
  17053. const retainedEntry = vars.get('retained');
  17054. const numRetained = retainedEntry?.operands?.length || 0;
  17055. const i1Type = new _.IntegerType('i1');
  17056. for (let i = 0; i < numRetained; i++) {
  17057. op.addTypes([i1Type]);
  17058. }
  17059. return;
  17060. }
  17061. super.inferResultTypes(op, vars);
  17062. }
  17063. };
  17064. _.SCFDialect = class extends _.Dialect {
  17065. constructor(operations) {
  17066. super(operations, 'scf');
  17067. this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));
  17068. }
  17069. parseOperation(parser, result) {
  17070. if (result.op === 'scf.for') {
  17071. return this.parseForOp(parser, result);
  17072. }
  17073. if (result.op === 'scf.if') {
  17074. return this.parseIfOp(parser, result);
  17075. }
  17076. if (result.op === 'scf.while') {
  17077. return this.parseWhileOp(parser, result);
  17078. }
  17079. if (result.op === 'scf.forall') {
  17080. return this.parseForallOp(parser, result);
  17081. }
  17082. if (result.op === 'scf.forall.in_parallel') {
  17083. return this.parseInParallelOp(parser, result);
  17084. }
  17085. if (result.op === 'scf.parallel') {
  17086. return this.parseParallelOp(parser, result);
  17087. }
  17088. if (result.op === 'scf.execute_region') {
  17089. return this.parseExecuteRegionOp(parser, result);
  17090. }
  17091. return super.parseOperation(parser, result);
  17092. }
  17093. parseForOp(parser, result) {
  17094. if (parser.parseOptionalKeyword('unsigned')) {
  17095. result.addAttribute('unsignedCmp', true);
  17096. }
  17097. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  17098. return false;
  17099. }
  17100. const inductionVar = parser.parseOperand();
  17101. if (!parser.parseOptionalEqual()) {
  17102. return false;
  17103. }
  17104. const indexType = new _.IndexType();
  17105. let unresolvedLb = null;
  17106. if (parser.getToken().is(_.Token.percent_identifier)) {
  17107. unresolvedLb = parser.parseOperand();
  17108. } else {
  17109. return false;
  17110. }
  17111. if (!parser.parseOptionalKeyword('to')) {
  17112. return false;
  17113. }
  17114. let unresolvedUb = null;
  17115. if (parser.getToken().is(_.Token.percent_identifier)) {
  17116. unresolvedUb = parser.parseOperand();
  17117. } else {
  17118. return false;
  17119. }
  17120. if (!parser.parseOptionalKeyword('step')) {
  17121. return false;
  17122. }
  17123. let unresolvedStep = null;
  17124. if (parser.getToken().is(_.Token.percent_identifier)) {
  17125. unresolvedStep = parser.parseOperand();
  17126. } else {
  17127. return false;
  17128. }
  17129. parser.resolveOperands([unresolvedLb, unresolvedUb, unresolvedStep], [indexType, indexType, indexType], result.operands);
  17130. let initArgsCount = 0;
  17131. if (parser.parseOptionalKeyword('iter_args')) {
  17132. const unresolvedIterArgs = [];
  17133. if (parser.parseOptionalLParen()) {
  17134. while (!parser.parseOptionalRParen()) {
  17135. if (parser.getToken().is(_.Token.percent_identifier)) {
  17136. parser.parseOperand(); // Skip the loop-carried variable name
  17137. }
  17138. if (parser.parseOptionalEqual()) {
  17139. if (parser.getToken().is(_.Token.percent_identifier)) {
  17140. unresolvedIterArgs.push(parser.parseOperand());
  17141. } else {
  17142. const value = parser.parseAttribute();
  17143. if (value) {
  17144. // Attribute values aren't operands - skip for now
  17145. }
  17146. }
  17147. }
  17148. parser.parseOptionalComma();
  17149. }
  17150. }
  17151. result.addTypes(parser.parseArrowTypeList());
  17152. const iterArgTypes = result.types.map((t) => t || indexType);
  17153. parser.resolveOperands(unresolvedIterArgs, iterArgTypes, result.operands);
  17154. initArgsCount = unresolvedIterArgs.length;
  17155. }
  17156. if (parser.parseOptionalColon()) {
  17157. parser.parseType();
  17158. }
  17159. if (parser.getToken().is(_.Token.l_brace)) {
  17160. const region = {};
  17161. parser.parseRegion(region);
  17162. if (region.blocks && region.blocks.length > 0) {
  17163. if (!region.blocks[0].arguments) {
  17164. region.blocks[0].arguments = [];
  17165. }
  17166. if (region.blocks[0].arguments.length > 0) {
  17167. region.blocks[0].arguments[0] = { value: inductionVar };
  17168. } else {
  17169. region.blocks[0].arguments.push({ value: inductionVar });
  17170. }
  17171. }
  17172. result.regions.push(region);
  17173. }
  17174. parser.parseOptionalAttrDict(result.attributes);
  17175. result.addAttribute('operandSegmentSizes', [1, 1, 1, initArgsCount]);
  17176. return true;
  17177. }
  17178. parseIfOp(parser, result) {
  17179. // Reference impl: condition operand is of type i1
  17180. let unresolvedCond = null;
  17181. if (parser.getToken().is(_.Token.percent_identifier)) {
  17182. unresolvedCond = parser.parseOperand();
  17183. } else {
  17184. return false;
  17185. }
  17186. const i1Type = new _.IntegerType('i1');
  17187. parser.resolveOperands([unresolvedCond], [i1Type], result.operands);
  17188. result.addTypes(parser.parseOptionalArrowTypeList());
  17189. if (parser.getToken().is(_.Token.l_brace)) {
  17190. const region = result.addRegion();
  17191. parser.parseRegion(region);
  17192. } else {
  17193. return false;
  17194. }
  17195. if (parser.parseOptionalKeyword('else')) {
  17196. if (parser.getToken().is(_.Token.l_brace)) {
  17197. const region = result.addRegion();
  17198. parser.parseRegion(region);
  17199. }
  17200. }
  17201. parser.parseOptionalAttrDict(result.attributes);
  17202. return true;
  17203. }
  17204. parseWhileOp(parser, result) {
  17205. const unresolvedOperands = [];
  17206. if (parser.parseOptionalLParen()) {
  17207. while (!parser.parseOptionalRParen()) {
  17208. if (parser.getToken().is(_.Token.percent_identifier)) {
  17209. parser.parseOperand(); // Skip variable name
  17210. }
  17211. if (parser.parseOptionalEqual()) {
  17212. if (parser.getToken().is(_.Token.percent_identifier)) {
  17213. unresolvedOperands.push(parser.parseOperand());
  17214. }
  17215. // Note: attribute values are not operands, skip them
  17216. }
  17217. parser.parseOptionalComma();
  17218. }
  17219. }
  17220. if (parser.parseOptionalColon()) {
  17221. const types = [];
  17222. if (parser.parseOptionalLParen()) {
  17223. while (!parser.parseOptionalRParen()) {
  17224. types.push(parser.parseType());
  17225. parser.parseOptionalComma();
  17226. }
  17227. } else {
  17228. types.push(parser.parseType());
  17229. }
  17230. parser.resolveOperands(unresolvedOperands, types, result.operands);
  17231. result.addTypes(parser.parseOptionalArrowTypeList());
  17232. }
  17233. if (parser.getToken().is(_.Token.l_brace)) {
  17234. const region = result.addRegion();
  17235. parser.parseRegion(region);
  17236. }
  17237. if (parser.parseOptionalKeyword('do')) {
  17238. if (parser.getToken().is(_.Token.l_brace)) {
  17239. const region = result.addRegion();
  17240. parser.parseRegion(region);
  17241. }
  17242. }
  17243. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  17244. return true;
  17245. }
  17246. parseForallOp(parser, result) {
  17247. const indexType = new _.IndexType();
  17248. const inductionVars = [];
  17249. if (!parser.parseOptionalLParen()) {
  17250. return false;
  17251. }
  17252. while (!parser.parseOptionalRParen()) {
  17253. if (parser.getToken().is(_.Token.percent_identifier)) {
  17254. inductionVars.push(parser.parseOperand().name);
  17255. } else {
  17256. return false;
  17257. }
  17258. if (!parser.parseOptionalComma()) {
  17259. if (parser.getToken().is(_.Token.r_paren)) {
  17260. parser.parseOptionalRParen();
  17261. break;
  17262. }
  17263. return false;
  17264. }
  17265. }
  17266. const isNormalized = parser.parseOptionalKeyword('in');
  17267. if (!isNormalized && !parser.parseOptionalEqual()) {
  17268. return false;
  17269. }
  17270. // Helper to parse bounds list - only SSA values become operands, integers are static
  17271. const parseBoundsList = () => {
  17272. const bounds = [];
  17273. if (!parser.parseOptionalLParen()) {
  17274. return bounds;
  17275. }
  17276. while (!parser.parseOptionalRParen()) {
  17277. if (parser.getToken().is(_.Token.percent_identifier)) {
  17278. bounds.push(parser.parseOperand());
  17279. } else if (parser.getToken().is(_.Token.integer)) {
  17280. parser.consumeToken(_.Token.integer); // Skip static bound
  17281. }
  17282. parser.parseOptionalComma();
  17283. }
  17284. return bounds;
  17285. };
  17286. if (isNormalized) {
  17287. // Normalized form: in (bounds)
  17288. const bounds = parseBoundsList();
  17289. parser.resolveOperands(bounds, bounds.map(() => indexType), result.operands);
  17290. } else {
  17291. // Range form: = (lb) to (ub) step (step)
  17292. const lowerBounds = parseBoundsList();
  17293. parser.resolveOperands(lowerBounds, lowerBounds.map(() => indexType), result.operands);
  17294. if (!parser.parseOptionalKeyword('to')) {
  17295. return false;
  17296. }
  17297. const upperBounds = parseBoundsList();
  17298. parser.resolveOperands(upperBounds, upperBounds.map(() => indexType), result.operands);
  17299. if (!parser.parseOptionalKeyword('step')) {
  17300. return false;
  17301. }
  17302. const steps = parseBoundsList();
  17303. parser.resolveOperands(steps, steps.map(() => indexType), result.operands);
  17304. }
  17305. if (parser.parseOptionalKeyword('shared_outs')) {
  17306. if (!parser.parseOptionalLParen()) {
  17307. return false;
  17308. }
  17309. while (!parser.parseOptionalRParen()) {
  17310. if (parser.getToken().is(_.Token.percent_identifier)) {
  17311. parser.parseOperand(); // Skip arg name
  17312. }
  17313. if (parser.parseOptionalEqual()) {
  17314. if (parser.getToken().is(_.Token.percent_identifier)) {
  17315. const operand = parser.parseOperand();
  17316. parser.resolveOperand(operand, null, result.operands);
  17317. } else {
  17318. parser.parseAttribute(); // Skip attribute value
  17319. }
  17320. }
  17321. parser.parseOptionalComma();
  17322. }
  17323. }
  17324. if (parser.parseOptionalArrow()) {
  17325. if (parser.parseOptionalLParen()) {
  17326. while (!parser.parseOptionalRParen()) {
  17327. const type = parser.parseType();
  17328. result.addTypes([type]);
  17329. parser.parseOptionalComma();
  17330. }
  17331. } else {
  17332. const type = parser.parseType();
  17333. result.addTypes([type]);
  17334. }
  17335. }
  17336. if (parser.getToken().is(_.Token.l_brace)) {
  17337. const region = result.addRegion();
  17338. parser.parseRegion(region);
  17339. } else {
  17340. return false;
  17341. }
  17342. parser.parseOptionalAttrDict(result.attributes);
  17343. return true;
  17344. }
  17345. parseParallelOp(parser, result) {
  17346. const indexType = new _.IndexType();
  17347. const inductionVars = [];
  17348. if (!parser.parseOptionalLParen()) {
  17349. return false;
  17350. }
  17351. while (!parser.parseOptionalRParen()) {
  17352. if (parser.getToken().is(_.Token.percent_identifier)) {
  17353. inductionVars.push(parser.parseOperand().name);
  17354. } else {
  17355. return false;
  17356. }
  17357. parser.parseOptionalComma();
  17358. }
  17359. if (!parser.parseOptionalEqual()) {
  17360. return false;
  17361. }
  17362. const lowerBounds = [];
  17363. if (!parser.parseOptionalLParen()) {
  17364. return false;
  17365. }
  17366. while (!parser.parseOptionalRParen()) {
  17367. if (parser.getToken().is(_.Token.percent_identifier)) {
  17368. lowerBounds.push(parser.parseOperand());
  17369. } else {
  17370. return false;
  17371. }
  17372. parser.parseOptionalComma();
  17373. }
  17374. parser.resolveOperands(lowerBounds, lowerBounds.map(() => indexType), result.operands);
  17375. if (!parser.parseOptionalKeyword('to')) {
  17376. return false;
  17377. }
  17378. const upperBounds = [];
  17379. if (!parser.parseOptionalLParen()) {
  17380. return false;
  17381. }
  17382. while (!parser.parseOptionalRParen()) {
  17383. if (parser.getToken().is(_.Token.percent_identifier)) {
  17384. upperBounds.push(parser.parseOperand());
  17385. } else {
  17386. return false;
  17387. }
  17388. parser.parseOptionalComma();
  17389. }
  17390. parser.resolveOperands(upperBounds, upperBounds.map(() => indexType), result.operands);
  17391. if (!parser.parseOptionalKeyword('step')) {
  17392. return false;
  17393. }
  17394. const steps = [];
  17395. if (!parser.parseOptionalLParen()) {
  17396. return false;
  17397. }
  17398. while (!parser.parseOptionalRParen()) {
  17399. if (parser.getToken().is(_.Token.percent_identifier)) {
  17400. steps.push(parser.parseOperand());
  17401. } else {
  17402. return false;
  17403. }
  17404. parser.parseOptionalComma();
  17405. }
  17406. parser.resolveOperands(steps, steps.map(() => indexType), result.operands);
  17407. if (parser.parseOptionalKeyword('init')) {
  17408. const initVals = [];
  17409. if (!parser.parseOptionalLParen()) {
  17410. return false;
  17411. }
  17412. while (!parser.parseOptionalRParen()) {
  17413. if (parser.getToken().is(_.Token.percent_identifier)) {
  17414. initVals.push(parser.parseOperand());
  17415. } else {
  17416. const value = parser.parseAttribute();
  17417. if (value) {
  17418. initVals.push(value);
  17419. }
  17420. }
  17421. parser.parseOptionalComma();
  17422. }
  17423. // Init values type inferred from definition
  17424. parser.resolveOperands(initVals, initVals.map(() => null), result.operands);
  17425. }
  17426. if (parser.parseOptionalArrow()) {
  17427. if (parser.parseOptionalLParen()) {
  17428. while (!parser.parseOptionalRParen()) {
  17429. const type = parser.parseType();
  17430. result.addTypes([type]);
  17431. parser.parseOptionalComma();
  17432. }
  17433. } else {
  17434. const type = parser.parseType();
  17435. result.addTypes([type]);
  17436. }
  17437. }
  17438. if (parser.getToken().is(_.Token.l_brace)) {
  17439. const region = {};
  17440. parser.parseRegion(region);
  17441. if (region.blocks && region.blocks.length > 0 && inductionVars.length > 0) {
  17442. if (!region.blocks[0].arguments) {
  17443. region.blocks[0].arguments = [];
  17444. }
  17445. for (const iv of inductionVars) {
  17446. region.blocks[0].arguments.push({ value: iv });
  17447. }
  17448. }
  17449. result.regions.push(region);
  17450. } else {
  17451. return false;
  17452. }
  17453. parser.parseOptionalAttrDict(result.attributes);
  17454. return true;
  17455. }
  17456. parseInParallelOp(parser, result) {
  17457. // scf.forall.in_parallel { region }
  17458. if (parser.getToken().is(_.Token.l_brace)) {
  17459. const region = result.addRegion();
  17460. parser.parseRegion(region);
  17461. } else {
  17462. return false;
  17463. }
  17464. parser.parseOptionalAttrDict(result.attributes);
  17465. return true;
  17466. }
  17467. parseSwitchCases(parser, op, casesAttrName) {
  17468. const caseValues = [];
  17469. while (parser.parseOptionalKeyword('case')) {
  17470. if (parser.getToken().isNot(_.Token.integer)) {
  17471. break;
  17472. }
  17473. const value = parser.parseInteger();
  17474. caseValues.push(value);
  17475. if (parser.getToken().is(_.Token.l_brace)) {
  17476. const region = op.addRegion();
  17477. parser.parseRegion(region);
  17478. } else {
  17479. break;
  17480. }
  17481. }
  17482. if (casesAttrName) {
  17483. op.addAttribute(casesAttrName, caseValues);
  17484. }
  17485. }
  17486. parseExecuteRegionOp(parser, result) {
  17487. result.addTypes(parser.parseOptionalArrowTypeList());
  17488. if (parser.parseOptionalKeyword('no_inline')) {
  17489. result.addAttribute('no_inline', true);
  17490. }
  17491. if (parser.getToken().is(_.Token.l_brace)) {
  17492. const region = result.addRegion();
  17493. parser.parseRegion(region);
  17494. }
  17495. parser.parseOptionalAttrDict(result.attributes);
  17496. return true;
  17497. }
  17498. };
  17499. _.ShapeDialect = class extends _.Dialect {
  17500. constructor(operations) {
  17501. super(operations, 'shape');
  17502. }
  17503. parseType(parser, dialect) {
  17504. const typeName = parser.parseOptionalKeyword();
  17505. if (!typeName) {
  17506. return null;
  17507. }
  17508. let type = `!${dialect}.${typeName}`;
  17509. if (typeName === 'value' && parser.getToken().is('_')) {
  17510. parser.consumeToken('_');
  17511. const subType = parser.getToken().getSpelling().str();
  17512. parser.consumeToken(_.Token.bare_identifier);
  17513. type += `_${subType}`;
  17514. }
  17515. const simpleTypes = ['shape', 'witness', 'size', 'value_shape'];
  17516. if (simpleTypes.includes(type.substring(7))) { // Remove "!shape." prefix
  17517. return new _.Type(type);
  17518. }
  17519. return null;
  17520. }
  17521. parseOperation(parser, result) {
  17522. if (result.op === 'shape.func') {
  17523. parser.parseFunctionOp(result, false);
  17524. return true;
  17525. }
  17526. if (result.op === 'shape.assuming') {
  17527. return this.parseAssumingOp(parser, result);
  17528. }
  17529. if (result.op === 'shape.const_shape') {
  17530. return this.parseConstShapeOp(parser, result);
  17531. }
  17532. if (result.op === 'shape.reduce') {
  17533. return this.parseReduceOp(parser, result);
  17534. }
  17535. if (result.op === 'shape.function_library') {
  17536. return this.parseFunctionLibraryOp(parser, result);
  17537. }
  17538. return super.parseOperation(parser, result);
  17539. }
  17540. parseAssumingOp(parser, result) {
  17541. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  17542. return false;
  17543. }
  17544. const unresolvedWitness = parser.parseOperand();
  17545. const witnessType = new _.Type('!shape.witness');
  17546. parser.resolveOperand(unresolvedWitness, witnessType, result.operands);
  17547. if (parser.parseOptionalArrow()) {
  17548. const types = parser.parseFunctionResultTypes();
  17549. result.addTypes(types);
  17550. }
  17551. if (parser.getToken().is(_.Token.l_brace)) {
  17552. const region = result.addRegion();
  17553. parser.parseRegion(region);
  17554. }
  17555. parser.parseOptionalAttrDict(result.attributes);
  17556. return true;
  17557. }
  17558. parseConstShapeOp(parser, result) {
  17559. parser.parseOptionalAttrDict(result.attributes);
  17560. const extents = parser.parseAttribute();
  17561. result.addAttribute('shape', extents);
  17562. if (parser.parseOptionalColon()) {
  17563. const type = parser.parseType();
  17564. result.addTypes([type]);
  17565. }
  17566. return true;
  17567. }
  17568. parseReduceOp(parser, result) {
  17569. if (parser.getToken().isNot(_.Token.l_paren)) {
  17570. return false;
  17571. }
  17572. parser.parseOptionalLParen();
  17573. const unresolvedOperands = [];
  17574. while (parser.getToken().is(_.Token.percent_identifier)) {
  17575. unresolvedOperands.push(parser.parseOperand());
  17576. if (!parser.parseOptionalComma()) {
  17577. break;
  17578. }
  17579. }
  17580. parser.parseOptionalRParen();
  17581. let shapeType = new _.Type('!shape.shape');
  17582. if (parser.parseOptionalColon()) {
  17583. shapeType = parser.parseType();
  17584. }
  17585. const resultTypes = [];
  17586. if (parser.parseOptionalArrow()) {
  17587. const types = parser.parseFunctionResultTypes();
  17588. result.addTypes(types);
  17589. resultTypes.push(...types);
  17590. }
  17591. // First operand is the shape, rest are init values with result types
  17592. if (unresolvedOperands.length > 0) {
  17593. parser.resolveOperand(unresolvedOperands[0], shapeType, result.operands);
  17594. for (let i = 1; i < unresolvedOperands.length; i++) {
  17595. const initType = resultTypes[i - 1] || null;
  17596. parser.resolveOperand(unresolvedOperands[i], initType, result.operands);
  17597. }
  17598. }
  17599. if (parser.getToken().is(_.Token.l_brace)) {
  17600. const region = result.addRegion();
  17601. parser.parseRegion(region);
  17602. }
  17603. parser.parseOptionalAttrDict(result.attributes);
  17604. return true;
  17605. }
  17606. parseFunctionLibraryOp(parser, result) {
  17607. parser.parseSymbolName('sym_name', result.attributes);
  17608. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  17609. if (parser.getToken().is(_.Token.l_brace)) {
  17610. const region = result.addRegion();
  17611. parser.parseRegion(region);
  17612. }
  17613. if (parser.parseOptionalKeyword('mapping')) {
  17614. const mapping = parser.parseAttribute();
  17615. result.addAttribute('mapping', mapping);
  17616. }
  17617. return true;
  17618. }
  17619. };
  17620. _.SparseTensorDialect = class extends _.Dialect {
  17621. constructor(operations) {
  17622. super(operations, 'sparse_tensor');
  17623. this.registerCustomDirective('LevelRange', this.parseLevelRange.bind(this));
  17624. }
  17625. parseLevelRange(parser, op, startAttr, endAttr) {
  17626. const loLvl = parser.parseInteger();
  17627. const hiLvl = parser.parseOptionalKeyword('to') ? parser.parseInteger() : loLvl + 1;
  17628. if (startAttr && endAttr) {
  17629. op.addAttribute(startAttr, loLvl);
  17630. op.addAttribute(endAttr, hiLvl);
  17631. }
  17632. }
  17633. parseOperation(parser, result) {
  17634. if (result.op === 'sparse_tensor.iterate') {
  17635. return this.parseIterateOp(parser, result);
  17636. }
  17637. if (result.op === 'sparse_tensor.coiterate') {
  17638. return this.parseCoIterateOp(parser, result);
  17639. }
  17640. return super.parseOperation(parser, result);
  17641. }
  17642. parseIterateOp(parser, result) {
  17643. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  17644. return false;
  17645. }
  17646. const regionArgs = [];
  17647. const iteratorArg = parser.parseOperand(); // iterator name (block arg)
  17648. regionArgs.push({ name: iteratorArg.name, type: null }); // type determined by tensor
  17649. if (!parser.parseOptionalKeyword('in')) {
  17650. return false;
  17651. }
  17652. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  17653. return false;
  17654. }
  17655. const unresolvedTensor = parser.parseOperand();
  17656. const iterArgNames = [];
  17657. const initValues = [];
  17658. if (parser.parseOptionalKeyword('at')) {
  17659. parser.parseOptionalLParen();
  17660. while (parser.getToken().is(_.Token.percent_identifier) || parser.getToken().is(_.Token.bare_identifier)) {
  17661. parser.consumeToken();
  17662. if (!parser.parseOptionalComma()) {
  17663. break;
  17664. }
  17665. }
  17666. parser.parseOptionalRParen();
  17667. }
  17668. if (parser.parseOptionalKeyword('iter_args')) {
  17669. parser.parseOptionalLParen();
  17670. while (parser.getToken().is(_.Token.percent_identifier)) {
  17671. const iterArg = parser.parseOperand();
  17672. iterArgNames.push(iterArg.name);
  17673. if (parser.parseOptionalEqual()) {
  17674. initValues.push(parser.parseOperand());
  17675. }
  17676. if (!parser.parseOptionalComma()) {
  17677. break;
  17678. }
  17679. }
  17680. parser.parseOptionalRParen();
  17681. }
  17682. let tensorType = null;
  17683. if (parser.parseOptionalColon()) {
  17684. tensorType = parser.parseType();
  17685. }
  17686. const resultTypes = [];
  17687. if (parser.parseOptionalArrow()) {
  17688. const types = parser.parseFunctionResultTypes();
  17689. result.addTypes(types);
  17690. resultTypes.push(...types);
  17691. }
  17692. // Add iter_args to region args with their result types
  17693. for (let i = 0; i < iterArgNames.length; i++) {
  17694. const argType = resultTypes[i] || null;
  17695. regionArgs.push({ name: iterArgNames[i], type: argType });
  17696. }
  17697. parser.resolveOperand(unresolvedTensor, tensorType, result.operands);
  17698. // iter_args block args don't go to operands, but init values do
  17699. for (let i = 0; i < initValues.length; i++) {
  17700. const initType = resultTypes[i] || null;
  17701. parser.resolveOperand(initValues[i], initType, result.operands);
  17702. }
  17703. if (parser.getToken().is(_.Token.l_brace)) {
  17704. const region = result.addRegion();
  17705. parser.parseRegion(region, regionArgs);
  17706. }
  17707. parser.parseOptionalAttrDict(result.attributes);
  17708. return true;
  17709. }
  17710. parseCoIterateOp(parser, result) {
  17711. if (!parser.parseOptionalLParen()) {
  17712. return false;
  17713. }
  17714. const unresolvedTensors = [];
  17715. while (parser.getToken().is(_.Token.percent_identifier)) {
  17716. unresolvedTensors.push(parser.parseOperand());
  17717. if (!parser.parseOptionalComma()) {
  17718. break;
  17719. }
  17720. }
  17721. parser.parseOptionalRParen();
  17722. if (parser.parseOptionalKeyword('at')) {
  17723. parser.parseOptionalLParen();
  17724. while (parser.getToken().is(_.Token.percent_identifier) || parser.getToken().is(_.Token.bare_identifier)) {
  17725. parser.consumeToken();
  17726. if (!parser.parseOptionalComma()) {
  17727. break;
  17728. }
  17729. }
  17730. parser.parseOptionalRParen();
  17731. }
  17732. const iterArgNames = [];
  17733. const initValues = [];
  17734. if (parser.parseOptionalKeyword('iter_args')) {
  17735. parser.parseOptionalLParen();
  17736. while (parser.getToken().is(_.Token.percent_identifier)) {
  17737. const iterArg = parser.parseOperand(); // block arg name
  17738. iterArgNames.push(iterArg.name);
  17739. if (parser.parseOptionalEqual()) {
  17740. initValues.push(parser.parseOperand());
  17741. }
  17742. if (!parser.parseOptionalComma()) {
  17743. break;
  17744. }
  17745. }
  17746. parser.parseOptionalRParen();
  17747. }
  17748. const tensorTypes = [];
  17749. if (parser.parseOptionalColon()) {
  17750. parser.parseOptionalLParen();
  17751. while (parser.getToken().isNot(_.Token.r_paren)) {
  17752. tensorTypes.push(parser.parseType());
  17753. if (!parser.parseOptionalComma()) {
  17754. break;
  17755. }
  17756. }
  17757. parser.parseOptionalRParen();
  17758. }
  17759. const resultTypes = [];
  17760. if (parser.parseOptionalArrow()) {
  17761. const types = parser.parseFunctionResultTypes();
  17762. result.addTypes(types);
  17763. resultTypes.push(...types);
  17764. }
  17765. const regionArgs = [];
  17766. for (let i = 0; i < iterArgNames.length; i++) {
  17767. const argType = resultTypes[i] || null;
  17768. regionArgs.push({ name: iterArgNames[i], type: argType });
  17769. }
  17770. for (let i = 0; i < unresolvedTensors.length; i++) {
  17771. const tensorType = tensorTypes[i] || null;
  17772. parser.resolveOperand(unresolvedTensors[i], tensorType, result.operands);
  17773. }
  17774. for (let i = 0; i < initValues.length; i++) {
  17775. const initType = resultTypes[i] || null;
  17776. parser.resolveOperand(initValues[i], initType, result.operands);
  17777. }
  17778. while (parser.parseOptionalKeyword('case')) {
  17779. const caseArgs = [...regionArgs]; // Start with iter_args
  17780. while (parser.getToken().is(_.Token.percent_identifier) || parser.getToken().is(_.Token.bare_identifier)) {
  17781. const caseArg = parser.getToken().getSpelling().str();
  17782. parser.consumeToken();
  17783. if (caseArg.startsWith('%')) {
  17784. caseArgs.push({ name: caseArg, type: null });
  17785. }
  17786. if (!parser.parseOptionalComma()) {
  17787. break;
  17788. }
  17789. }
  17790. if (parser.getToken().is(_.Token.l_brace)) {
  17791. const region = result.addRegion();
  17792. parser.parseRegion(region, caseArgs);
  17793. }
  17794. }
  17795. parser.parseOptionalAttrDict(result.attributes);
  17796. return true;
  17797. }
  17798. };
  17799. _.FuncDialect = class extends _.Dialect {
  17800. constructor(operations) {
  17801. super(operations, 'func');
  17802. }
  17803. parseOperation(parser, result) {
  17804. if (result.op === 'func.func') {
  17805. parser.parseFunctionOp(result, false);
  17806. return true;
  17807. }
  17808. return super.parseOperation(parser, result);
  17809. }
  17810. };
  17811. _.GpuDialect = class extends _.Dialect {
  17812. constructor(operations) {
  17813. super(operations, 'gpu');
  17814. this.registerCustomDirective('AllReduceOperation', this.parseAllReduceOperation.bind(this));
  17815. this.registerCustomDirective('LaunchFuncOperands', this.parseLaunchFuncOperands.bind(this));
  17816. this.registerCustomDirective('AsyncDependencies', this.parseAsyncDependencies.bind(this));
  17817. this.registerCustomDirective('LaunchDimType', this.parseLaunchDimType.bind(this));
  17818. this.registerCustomDirective('OffloadingHandler', this.parseOffloadingHandler.bind(this));
  17819. }
  17820. parseAllReduceOperation(parser, op, attrName = 'op') {
  17821. const validOps = ['add', 'mul', 'minui', 'minsi', 'minnumf', 'maxui', 'maxsi', 'maxnumf', 'and', 'or', 'xor', 'minimumf', 'maximumf'];
  17822. if (parser.getToken().is(_.Token.bare_identifier)) {
  17823. const opName = parser.getTokenSpelling().str();
  17824. if (validOps.includes(opName)) {
  17825. parser.consumeToken(_.Token.bare_identifier);
  17826. op.addAttribute(attrName, opName);
  17827. }
  17828. }
  17829. }
  17830. parseLaunchDimType(parser, op, typeArg1, typeArg2, clusterTypeArg1, clusterTypeArg2, clusterTypeArg3) {
  17831. // typeArg1 = type($gridSizeX), typeArg2 = ref($clusterSizeX)
  17832. // clusterTypeArg1/2/3 = type($clusterSizeX/Y/Z)
  17833. let dimType = new _.IndexType();
  17834. if (parser.parseOptionalColon()) {
  17835. dimType = parser.parseType();
  17836. }
  17837. // Push type to gridSizeX types array
  17838. if (Array.isArray(typeArg1)) {
  17839. typeArg1.push(dimType);
  17840. }
  17841. // If clusters are present (ref($clusterSizeX) has values), push to cluster type arrays
  17842. const hasCluster = Array.isArray(typeArg2) && typeArg2.length > 0;
  17843. if (hasCluster) {
  17844. if (Array.isArray(clusterTypeArg1)) {
  17845. clusterTypeArg1.push(dimType);
  17846. }
  17847. if (Array.isArray(clusterTypeArg2)) {
  17848. clusterTypeArg2.push(dimType);
  17849. }
  17850. if (Array.isArray(clusterTypeArg3)) {
  17851. clusterTypeArg3.push(dimType);
  17852. }
  17853. }
  17854. }
  17855. parseOperation(parser, result) {
  17856. if (result.op === 'gpu.func') {
  17857. parser.parseOptionalVisibilityKeyword(result.attributes);
  17858. parser.parseSymbolName('sym_name', result.attributes);
  17859. const sig = parser.parseFunctionSignatureWithArguments(false);
  17860. const argTypes = sig.arguments.map((a) => a.type);
  17861. const type = new _.FunctionType(argTypes, sig.resultTypes);
  17862. result.addAttribute('function_type', new _.TypeAttrOf(type));
  17863. const allArgs = [...sig.arguments];
  17864. if (parser.parseOptionalKeyword('workgroup')) {
  17865. const workgroupResult = parser.parseFunctionArgumentList(false);
  17866. allArgs.push(...workgroupResult.arguments);
  17867. }
  17868. if (parser.parseOptionalKeyword('private')) {
  17869. const privateResult = parser.parseFunctionArgumentList(false);
  17870. allArgs.push(...privateResult.arguments);
  17871. }
  17872. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'kernel') {
  17873. parser.consumeToken();
  17874. result.addAttribute('gpu.kernel', true);
  17875. }
  17876. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  17877. if (parser.getToken().is(_.Token.l_brace)) {
  17878. const region = result.addRegion();
  17879. // gpu.func is IsolatedFromAbove
  17880. parser.parseRegion(region, allArgs, /* isIsolatedNameScope */ true);
  17881. }
  17882. return true;
  17883. }
  17884. if (result.op === 'gpu.launch') {
  17885. const indexType = new _.IndexType();
  17886. if (parser.parseOptionalKeyword('async')) {
  17887. if (parser.getNumResults() === 0) {
  17888. throw new mlir.Error(`Operation '${result.op}' needs to be named when marked 'async' ${parser.location()}`);
  17889. }
  17890. result.addTypes([new _.Type('!gpu.async.token')]);
  17891. }
  17892. const asyncDeps = parser.parseOperandList('optionalSquare');
  17893. const asyncTypes = asyncDeps.map(() => null);
  17894. parser.resolveOperands(asyncDeps, asyncTypes, result.operands);
  17895. if (parser.parseOptionalKeyword('clusters')) {
  17896. this.parseSizeAssignment(parser, result, indexType);
  17897. parser.parseKeyword('in');
  17898. this.parseSizeAssignment(parser, result, indexType);
  17899. }
  17900. parser.parseKeyword('blocks');
  17901. this.parseSizeAssignment(parser, result, indexType);
  17902. parser.parseKeyword('in');
  17903. this.parseSizeAssignment(parser, result, indexType);
  17904. parser.parseKeyword('threads');
  17905. this.parseSizeAssignment(parser, result, indexType);
  17906. parser.parseKeyword('in');
  17907. this.parseSizeAssignment(parser, result, indexType);
  17908. if (parser.parseOptionalKeyword('dynamic_shared_memory_size')) {
  17909. const operand = parser.parseOperand();
  17910. parser.resolveOperand(operand, indexType, result.operands);
  17911. }
  17912. if (parser.parseOptionalKeyword('module')) {
  17913. parser.parseLParen();
  17914. const moduleSymbol = parser.getToken().getSpelling().str();
  17915. parser.consumeToken(_.Token.at_identifier);
  17916. result.addAttribute('module', moduleSymbol);
  17917. parser.parseRParen();
  17918. }
  17919. if (parser.parseOptionalKeyword('function')) {
  17920. parser.parseLParen();
  17921. const funcSymbol = parser.getToken().getSpelling().str();
  17922. parser.consumeToken(_.Token.at_identifier);
  17923. result.addAttribute('function', funcSymbol);
  17924. parser.parseRParen();
  17925. }
  17926. if (parser.parseOptionalKeyword('workgroup')) {
  17927. parser.parseLParen();
  17928. while (parser.getToken().isNot(_.Token.r_paren)) {
  17929. parser.parseOperand();
  17930. parser.parseColon();
  17931. parser.parseType();
  17932. if (!parser.parseOptionalComma()) {
  17933. break;
  17934. }
  17935. }
  17936. parser.parseRParen();
  17937. }
  17938. if (parser.parseOptionalKeyword('private')) {
  17939. parser.parseLParen();
  17940. while (parser.getToken().isNot(_.Token.r_paren)) {
  17941. parser.parseOperand();
  17942. parser.parseColon();
  17943. parser.parseType();
  17944. if (!parser.parseOptionalComma()) {
  17945. break;
  17946. }
  17947. }
  17948. parser.parseRParen();
  17949. }
  17950. if (parser.getToken().is(_.Token.l_brace)) {
  17951. const region = result.addRegion();
  17952. // gpu.launch is IsolatedFromAbove
  17953. parser.parseRegion(region, undefined, /* isIsolatedNameScope */ true);
  17954. }
  17955. parser.parseOptionalAttrDict(result.attributes);
  17956. return true;
  17957. }
  17958. if (result.op === 'gpu.warp_execute_on_lane_0') {
  17959. return this.parseWarpExecuteOnLane0Op(parser, result);
  17960. }
  17961. return super.parseOperation(parser, result);
  17962. }
  17963. parseWarpExecuteOnLane0Op(parser, result) {
  17964. parser.parseLParen();
  17965. const unresolvedLaneId = parser.parseOperand();
  17966. const indexType = new _.IndexType();
  17967. parser.resolveOperand(unresolvedLaneId, indexType, result.operands);
  17968. parser.parseRParen();
  17969. parser.parseLSquare();
  17970. const warpSize = parser.getToken().getSpelling().str();
  17971. parser.consumeToken(_.Token.integer);
  17972. result.addAttribute('warp_size', parseInt(warpSize, 10));
  17973. parser.parseRSquare();
  17974. if (parser.parseOptionalKeyword('args')) {
  17975. parser.parseLParen();
  17976. const unresolvedArgs = parser.parseOperandList('none');
  17977. if (parser.parseOptionalColon()) {
  17978. const types = parser.parseTypeListNoParens();
  17979. parser.resolveOperands(unresolvedArgs, types, result.operands);
  17980. } else {
  17981. for (const arg of unresolvedArgs) {
  17982. parser.resolveOperand(arg, null, result.operands);
  17983. }
  17984. }
  17985. parser.parseRParen();
  17986. }
  17987. if (parser.parseOptionalArrow()) {
  17988. const types = parser.parseFunctionResultTypes();
  17989. if (result.types.length > 0) {
  17990. result.addTypes(types);
  17991. } else {
  17992. for (const type of types) {
  17993. result.addTypes([type]);
  17994. }
  17995. }
  17996. }
  17997. if (parser.getToken().is(_.Token.l_brace)) {
  17998. const region = result.addRegion();
  17999. parser.parseRegion(region);
  18000. }
  18001. parser.parseOptionalAttrDict(result.attributes);
  18002. return true;
  18003. }
  18004. parseSizeAssignment(parser, op, indexType) {
  18005. parser.parseLParen();
  18006. while (parser.getToken().isNot(_.Token.r_paren)) {
  18007. if (parser.getToken().is(_.Token.percent_identifier)) {
  18008. parser.parseOperand(); // Skip the LHS block arg
  18009. if (parser.parseOptionalEqual()) {
  18010. const operand = parser.parseOperand();
  18011. parser.resolveOperand(operand, indexType, op.operands);
  18012. }
  18013. if (!parser.parseOptionalComma()) {
  18014. break;
  18015. }
  18016. } else {
  18017. break;
  18018. }
  18019. }
  18020. parser.parseRParen();
  18021. }
  18022. parseLaunchFuncOperands(parser, op /*, args */) {
  18023. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'args') {
  18024. parser.consumeToken();
  18025. parser.parseLParen();
  18026. while (parser.getToken().isNot(_.Token.r_paren)) {
  18027. const operand = parser.parseOperand();
  18028. parser.parseColon();
  18029. const type = parser.parseType();
  18030. parser.resolveOperand(operand, type, op.operands);
  18031. if (parser.getToken().isNot(_.Token.r_paren)) {
  18032. parser.parseComma();
  18033. }
  18034. }
  18035. parser.parseRParen();
  18036. }
  18037. }
  18038. parseAsyncDependencies(parser, op, asyncTokenTypes, asyncDependencies) {
  18039. // custom<AsyncDependencies>(type($asyncToken), $asyncDependencies)
  18040. // If 'async' keyword is present, operation has async result token
  18041. const hasAsync = parser.parseOptionalKeyword('async');
  18042. if (hasAsync && Array.isArray(asyncTokenTypes)) {
  18043. asyncTokenTypes.push(new _.Type('!gpu.async.token'));
  18044. }
  18045. if (parser.parseOptionalLSquare()) {
  18046. while (parser.getToken().isNot(_.Token.r_square)) {
  18047. if (Array.isArray(asyncDependencies)) {
  18048. asyncDependencies.push(parser.parseOperand());
  18049. } else {
  18050. parser.parseOperand();
  18051. }
  18052. if (!parser.parseOptionalComma()) {
  18053. break;
  18054. }
  18055. }
  18056. parser.parseRSquare();
  18057. }
  18058. }
  18059. parseOffloadingHandler(parser /*, op, args */) {
  18060. if (parser.parseOptionalLess()) {
  18061. parser.parseAttribute();
  18062. parser.parseGreater();
  18063. }
  18064. }
  18065. };
  18066. _.ArmSMEDialect = class extends _.Dialect {
  18067. constructor(operations) {
  18068. super(operations, 'arm_sme');
  18069. this.registerCustomAttribute('ArmSME_TypeSizeAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  18070. this.registerCustomAttribute('ArmSME_TileSliceLayoutAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  18071. this.registerCustomAttribute('ArmSME_CombiningKindAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  18072. }
  18073. inferResultTypes(op, vars) {
  18074. if (op.op === 'arm_sme.outerproduct' && op.operands.length >= 2) {
  18075. const lhsType = op.operands[0].type;
  18076. if (lhsType instanceof _.VectorType && lhsType.shape.length === 1 && lhsType.scalableDims?.[0]) {
  18077. const size = lhsType.shape[0];
  18078. const tileType = new _.VectorType([size, size], lhsType.elementType, [true, true]);
  18079. op.addTypes([tileType]);
  18080. return;
  18081. }
  18082. }
  18083. super.inferResultTypes(op, vars);
  18084. }
  18085. };
  18086. _.ArmNeonDialect = class extends _.Dialect {
  18087. constructor(operations) {
  18088. super(operations, 'arm_neon');
  18089. }
  18090. };
  18091. _.ArmSVEDialect = class extends _.Dialect {
  18092. constructor(operations) {
  18093. super(operations, 'arm_sve');
  18094. }
  18095. };
  18096. _.AMDGPUDialect = class extends _.Dialect {
  18097. constructor(operations) {
  18098. super(operations, 'amdgpu');
  18099. this.registerCustomDirective('MNKDimensionList', this.parseMNKDimensionList.bind(this));
  18100. }
  18101. parseMNKDimensionList(parser, op, mAttr, nAttr, kAttr) {
  18102. const dimInfo = parser.parseDimensionListRanked(false, false);
  18103. const dims = dimInfo.dimensions;
  18104. if (dims.length >= 3 && mAttr && nAttr && kAttr) {
  18105. op.addAttribute(mAttr, dims[0]);
  18106. op.addAttribute(nAttr, dims[1]);
  18107. op.addAttribute(kAttr, dims[2]);
  18108. }
  18109. }
  18110. };
  18111. _.NVGPUDialect = class extends _.Dialect {
  18112. constructor(operations) {
  18113. super(operations, 'nvgpu');
  18114. this.registerCustomType('NVGPU_TensorMapDescriptor', this.parseTensorMapDescriptor.bind(this));
  18115. this.registerCustomType('NVGPU_WarpgroupAccumulator', this.parseWarpgroupAccumulator.bind(this));
  18116. this.registerCustomType('NVGPU_WarpgroupMatrixDescriptor', this.parseWarpgroupMatrixDescriptor.bind(this));
  18117. this.registerCustomType('NVGPU_MBarrierGroup', this.parseMBarrierGroup.bind(this));
  18118. }
  18119. parseTensorMapDescriptor(parser) {
  18120. if (parser.getToken().is(_.Token.less)) {
  18121. const content = parser.skip('<');
  18122. return new _.Type(`!nvgpu.tensormap.descriptor${content}`);
  18123. }
  18124. return null;
  18125. }
  18126. parseWarpgroupAccumulator(parser) {
  18127. if (parser.getToken().is(_.Token.less)) {
  18128. const content = parser.skip('<');
  18129. return new _.Type(`!nvgpu.warpgroup.accumulator${content}`);
  18130. }
  18131. return null;
  18132. }
  18133. parseWarpgroupMatrixDescriptor(parser) {
  18134. if (parser.getToken().is(_.Token.less)) {
  18135. const content = parser.skip('<');
  18136. return new _.Type(`!nvgpu.warpgroup.descriptor${content}`);
  18137. }
  18138. return null;
  18139. }
  18140. parseMBarrierGroup(parser) {
  18141. if (parser.getToken().is(_.Token.less)) {
  18142. const content = parser.skip('<');
  18143. return new _.Type(`!nvgpu.mbarrier.barrier${content}`);
  18144. }
  18145. return null;
  18146. }
  18147. };
  18148. _.NVVMDialect = class extends _.Dialect {
  18149. constructor(operations) {
  18150. super(operations, 'nvvm');
  18151. }
  18152. parseOperation(parser, result) {
  18153. // Reference: NVVMDialect.cpp - parseMmaOperand
  18154. // Helper to parse operand list in the format: name[operands]
  18155. const parseMmaOperand = (name) => {
  18156. parser.parseKeyword(name);
  18157. return parser.parseOperandList('optionalSquare');
  18158. };
  18159. // Reference: NVVMDialect.cpp - MmaOp::parse
  18160. if (result.op === 'nvvm.mma.sync') {
  18161. const fragsA = parseMmaOperand('A');
  18162. const fragsB = parseMmaOperand('B');
  18163. const fragsC = parseMmaOperand('C');
  18164. parser.parseOptionalAttrDict(result.attributes);
  18165. if (parser.parseOptionalColon()) {
  18166. const funcType = parser.parseFunctionType();
  18167. if (funcType instanceof _.FunctionType) {
  18168. parser.resolveOperands(fragsA, funcType.inputs, result.operands);
  18169. parser.resolveOperands(fragsB, funcType.inputs, result.operands);
  18170. parser.resolveOperands(fragsC, funcType.inputs, result.operands);
  18171. result.addTypes(funcType.results);
  18172. }
  18173. }
  18174. return true;
  18175. }
  18176. // Reference: NVVMDialect.cpp - MmaSpOp::parse
  18177. if (result.op === 'nvvm.mma.sp.sync') {
  18178. const fragsA = parseMmaOperand('A');
  18179. const fragsB = parseMmaOperand('B');
  18180. const fragsC = parseMmaOperand('C');
  18181. const fragsSparseMetadata = parseMmaOperand('sparseMetadata');
  18182. const fragsSelector = parseMmaOperand('selector');
  18183. parser.parseOptionalAttrDict(result.attributes);
  18184. if (parser.parseOptionalColon()) {
  18185. const funcType = parser.parseFunctionType();
  18186. if (funcType instanceof _.FunctionType) {
  18187. parser.resolveOperands(fragsA, funcType.inputs, result.operands);
  18188. parser.resolveOperands(fragsB, funcType.inputs, result.operands);
  18189. parser.resolveOperands(fragsC, funcType.inputs, result.operands);
  18190. parser.resolveOperands(fragsSparseMetadata, funcType.inputs, result.operands);
  18191. parser.resolveOperands(fragsSelector, funcType.inputs, result.operands);
  18192. result.addTypes(funcType.results);
  18193. }
  18194. }
  18195. return true;
  18196. }
  18197. // Reference: NVVMDialect.cpp - MmaBlockScaleOp::parse
  18198. if (result.op === 'nvvm.mma.block_scale') {
  18199. const fragsA = parseMmaOperand('A');
  18200. const fragsB = parseMmaOperand('B');
  18201. const fragsC = parseMmaOperand('C');
  18202. const scaleAOperands = parseMmaOperand('scaleA');
  18203. const scaleBOperands = parseMmaOperand('scaleB');
  18204. parser.parseOptionalAttrDict(result.attributes);
  18205. if (parser.parseOptionalColon()) {
  18206. const funcType = parser.parseFunctionType();
  18207. if (funcType instanceof _.FunctionType) {
  18208. parser.resolveOperands(fragsA, funcType.inputs, result.operands);
  18209. parser.resolveOperands(fragsB, funcType.inputs, result.operands);
  18210. parser.resolveOperands(fragsC, funcType.inputs, result.operands);
  18211. parser.resolveOperands(scaleAOperands, funcType.inputs, result.operands);
  18212. parser.resolveOperands(scaleBOperands, funcType.inputs, result.operands);
  18213. result.addTypes(funcType.results);
  18214. }
  18215. }
  18216. return true;
  18217. }
  18218. // Reference: NVVMDialect.cpp - MmaSpBlockScaleOp::parse
  18219. if (result.op === 'nvvm.mma.sp.block_scale') {
  18220. const fragsA = parseMmaOperand('A');
  18221. const fragsB = parseMmaOperand('B');
  18222. const fragsC = parseMmaOperand('C');
  18223. const metadataOperands = parseMmaOperand('sparseMetadata');
  18224. const selectorOperands = parseMmaOperand('selector');
  18225. const scaleAOperands = parseMmaOperand('scaleA');
  18226. const scaleBOperands = parseMmaOperand('scaleB');
  18227. parser.parseOptionalAttrDict(result.attributes);
  18228. if (parser.parseOptionalColon()) {
  18229. const funcType = parser.parseFunctionType();
  18230. if (funcType instanceof _.FunctionType) {
  18231. parser.resolveOperands(fragsA, funcType.inputs, result.operands);
  18232. parser.resolveOperands(fragsB, funcType.inputs, result.operands);
  18233. parser.resolveOperands(fragsC, funcType.inputs, result.operands);
  18234. parser.resolveOperands(metadataOperands, funcType.inputs, result.operands);
  18235. parser.resolveOperands(selectorOperands, funcType.inputs, result.operands);
  18236. parser.resolveOperands(scaleAOperands, funcType.inputs, result.operands);
  18237. parser.resolveOperands(scaleBOperands, funcType.inputs, result.operands);
  18238. result.addTypes(funcType.results);
  18239. }
  18240. }
  18241. return true;
  18242. }
  18243. return super.parseOperation(parser, result);
  18244. }
  18245. };
  18246. _.NVWSDialect = class extends _.Dialect {
  18247. constructor(operations) {
  18248. super(operations, 'nvws');
  18249. this.registerCustomType('NVWS_ArefType', this.parseArefTypeShorthand.bind(this));
  18250. }
  18251. parseArefTypeShorthand(parser) {
  18252. if (parser.getToken().is(_.Token.less)) {
  18253. const content = parser.skip('<');
  18254. return new _.Type(`!nvws.aref${content}`);
  18255. }
  18256. return parser.parseType();
  18257. }
  18258. parseOperation(parser, result) {
  18259. if (result.op === 'nvws.warp_group') {
  18260. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  18261. const numWarps = [];
  18262. let partitionIndex = 0;
  18263. while (parser.parseOptionalKeyword(`partition${partitionIndex}`)) {
  18264. parser.parseKeyword('num_warps');
  18265. parser.parseLParen();
  18266. const n = parseInt(parser.getToken().getSpelling().str(), 10);
  18267. parser.consumeToken(_.Token.integer);
  18268. numWarps.push(n);
  18269. parser.parseRParen();
  18270. const region = result.addRegion();
  18271. parser.parseRegion(region);
  18272. partitionIndex++;
  18273. }
  18274. result.addAttribute('numWarps', numWarps);
  18275. return true;
  18276. }
  18277. return super.parseOperation(parser, result);
  18278. }
  18279. };
  18280. _.OpenMPDialect = class extends _.Dialect {
  18281. constructor(operations) {
  18282. super(operations, 'omp');
  18283. this.registerCustomDirective('MapClause', this.parseMapClause.bind(this));
  18284. this.registerCustomDirective('CaptureType', this.parseCaptureType.bind(this));
  18285. this.registerCustomDirective('MembersIndex', this.parseMembersIndex.bind(this));
  18286. this.registerCustomDirective('PrivateReductionRegion', this.parsePrivateReductionRegion.bind(this));
  18287. this.registerCustomDirective('PrivateRegion', this.parsePrivateReductionRegion.bind(this));
  18288. this.registerCustomDirective('InReductionPrivateRegion', this.parsePrivateReductionRegion.bind(this));
  18289. this.registerCustomDirective('InReductionPrivateReductionRegion', this.parsePrivateReductionRegion.bind(this));
  18290. this.registerCustomDirective('TaskReductionRegion', this.parsePrivateReductionRegion.bind(this));
  18291. this.registerCustomDirective('UseDeviceAddrUseDevicePtrRegion', this.parsePrivateReductionRegion.bind(this));
  18292. this.registerCustomDirective('TargetOpRegion', this.parseTargetOpRegion.bind(this));
  18293. this.registerCustomDirective('ClauseAttr', this.parseClauseAttr.bind(this));
  18294. this.registerCustomDirective('DependVarList', this.parseDependVarList.bind(this));
  18295. this.registerCustomDirective('LoopTransformClis', this.parseLoopTransformClis.bind(this));
  18296. this.registerCustomDirective('SynchronizationHint', this.parseSynchronizationHint.bind(this));
  18297. this.registerCustomDirective('AlignedClause', this.parseAlignedClause.bind(this));
  18298. this.registerCustomDirective('ScheduleClause', this.parseScheduleClause.bind(this));
  18299. this.registerCustomDirective('AllocateAndAllocator', this.parseAllocateAndAllocator.bind(this));
  18300. this.registerCustomDirective('LinearClause', this.parseLinearClause.bind(this));
  18301. this.registerCustomDirective('UniformClause', this.parseUniformClause.bind(this));
  18302. this.registerCustomDirective('OrderClause', this.parseOrderClause.bind(this));
  18303. this.registerCustomDirective('Copyprivate', this.parseCopyprivate.bind(this));
  18304. this.registerCustomDirective('GrainsizeClause', this.parseGranularityClause.bind(this));
  18305. this.registerCustomDirective('NumTasksClause', this.parseGranularityClause.bind(this));
  18306. this.registerCustomDirective('AffinityClause', this.parseAffinityClause.bind(this));
  18307. this.registerCustomAttribute('DataSharingClauseTypeAttr', this.parseDataSharingClauseTypeAttr.bind(this));
  18308. this.registerCustomAttribute('ClauseCancelConstructTypeAttr', this.parseParenthesizedEnumAttr.bind(this));
  18309. this.registerCustomAttribute('ClauseDependAttr', this.parseParenthesizedEnumAttr.bind(this));
  18310. this.registerCustomAttribute('ClauseOrderingIncludeTypeAttr', this.parseParenthesizedEnumAttr.bind(this));
  18311. this.registerCustomAttribute('ClauseTypeAttr', this.parseParenthesizedEnumAttr.bind(this));
  18312. this.registerCustomAttribute('ClauseDistScheduleTypeAttr', this.parseParenthesizedEnumAttr.bind(this));
  18313. this.registerCustomAttribute('OrderModifierAttr', this.parseParenthesizedEnumAttr.bind(this));
  18314. }
  18315. parseOperation(parser, result) {
  18316. if (result.op === 'omp.loop_nest') {
  18317. return this.parseLoopNestOp(parser, result);
  18318. }
  18319. if (result.op === 'omp.canonical_loop') {
  18320. return this.parseCanonicalLoopOp(parser, result);
  18321. }
  18322. if (result.op === 'omp.unroll_heuristic') {
  18323. return this.parseUnrollHeuristicOp(parser, result);
  18324. }
  18325. if (result.op === 'omp.map.bounds') {
  18326. return this.parseMapBoundsOp(parser, result);
  18327. }
  18328. if (result.op === 'omp.target_allocmem') {
  18329. const unresolvedDevice = parser.parseOperand();
  18330. parser.parseColon();
  18331. const deviceType = parser.parseType();
  18332. parser.resolveOperand(unresolvedDevice, deviceType, result.operands);
  18333. parser.parseComma();
  18334. const inType = parser.parseType();
  18335. result.addAttribute('in_type', { value: inType, type: 'type' });
  18336. const unresolvedTypeparams = [];
  18337. if (parser.parseOptionalLParen()) {
  18338. while (parser.getToken().isNot(_.Token.r_paren)) {
  18339. unresolvedTypeparams.push(parser.parseOperand());
  18340. if (parser.getToken().isNot(_.Token.r_paren)) {
  18341. parser.parseOptionalComma();
  18342. }
  18343. }
  18344. parser.parseColon();
  18345. const types = parser.parseTypeList();
  18346. parser.resolveOperands(unresolvedTypeparams, types, result.operands);
  18347. parser.parseRParen();
  18348. }
  18349. const unresolvedShape = [];
  18350. while (parser.parseOptionalComma()) {
  18351. unresolvedShape.push(parser.parseOperand());
  18352. }
  18353. const indexType = new _.IndexType();
  18354. for (const s of unresolvedShape) {
  18355. parser.resolveOperand(s, indexType, result.operands);
  18356. }
  18357. parser.parseOptionalAttrDict(result.attributes);
  18358. result.addAttribute('operandSegmentSizes', [1, unresolvedTypeparams.length, unresolvedShape.length]);
  18359. result.addTypes([new _.IntegerType('i64')]);
  18360. return true;
  18361. }
  18362. return super.parseOperation(parser, result);
  18363. }
  18364. parseCanonicalLoopOp(parser, result) {
  18365. if (parser.parseOptionalLParen()) {
  18366. const cliOperand = parser.parseOperand();
  18367. // CLI operand is a loop handle, resolve with null type
  18368. parser.resolveOperand(cliOperand, null, result.operands);
  18369. parser.parseRParen();
  18370. }
  18371. const inductionVar = parser.parseOperand();
  18372. parser.parseColon();
  18373. const ivType = parser.parseType();
  18374. parser.parseKeyword('in');
  18375. parser.parseKeyword('range');
  18376. parser.parseLParen();
  18377. const rangeOperand = parser.parseOperand();
  18378. parser.resolveOperand(rangeOperand, null, result.operands);
  18379. parser.parseRParen();
  18380. if (parser.getToken().is(_.Token.l_brace)) {
  18381. const region = result.addRegion();
  18382. // Pass induction variable as region argument
  18383. const regionArgs = [{ name: inductionVar.name, type: ivType }];
  18384. parser.parseRegion(region, regionArgs);
  18385. }
  18386. parser.parseOptionalAttrDict(result.attributes);
  18387. return true;
  18388. }
  18389. parseUnrollHeuristicOp(parser, result) {
  18390. parser.parseLParen();
  18391. const applyee = parser.parseOperand();
  18392. // Applyee is a loop handle, resolve with null type
  18393. parser.resolveOperand(applyee, null, result.operands);
  18394. parser.parseRParen();
  18395. if (parser.parseOptionalArrow()) {
  18396. parser.parseLParen();
  18397. parser.parseRParen();
  18398. }
  18399. parser.parseOptionalAttrDict(result.attributes);
  18400. return true;
  18401. }
  18402. parseLoopNestOp(parser, result) {
  18403. // Parse CLI operands (loop handles)
  18404. const unresolvedCli = [];
  18405. if (parser.parseOptionalLParen()) {
  18406. while (parser.getToken().isNot(_.Token.r_paren)) {
  18407. unresolvedCli.push(parser.parseOperand());
  18408. if (!parser.parseOptionalComma()) {
  18409. break;
  18410. }
  18411. }
  18412. parser.parseRParen();
  18413. }
  18414. // Parse types for CLI operands
  18415. const cliTypes = [];
  18416. if (parser.parseOptionalColon()) {
  18417. while (parser.getToken().isNot(_.Token.equal) && parser.getToken().isNot(_.Token.l_brace)) {
  18418. cliTypes.push(parser.parseType());
  18419. if (!parser.parseOptionalComma()) {
  18420. break;
  18421. }
  18422. }
  18423. }
  18424. parser.resolveOperands(unresolvedCli, cliTypes, result.operands);
  18425. if (parser.parseOptionalEqual()) {
  18426. if (parser.parseOptionalLParen()) {
  18427. const unresolvedLb = [];
  18428. while (parser.getToken().isNot(_.Token.r_paren)) {
  18429. unresolvedLb.push(parser.parseOperand());
  18430. if (!parser.parseOptionalComma()) {
  18431. break;
  18432. }
  18433. }
  18434. parser.parseRParen();
  18435. for (const lb of unresolvedLb) {
  18436. parser.resolveOperand(lb, null, result.operands);
  18437. }
  18438. }
  18439. if (parser.parseOptionalKeyword('to')) {
  18440. if (parser.parseOptionalLParen()) {
  18441. const unresolvedUb = [];
  18442. while (parser.getToken().isNot(_.Token.r_paren)) {
  18443. unresolvedUb.push(parser.parseOperand());
  18444. if (!parser.parseOptionalComma()) {
  18445. break;
  18446. }
  18447. }
  18448. parser.parseRParen();
  18449. for (const ub of unresolvedUb) {
  18450. parser.resolveOperand(ub, null, result.operands);
  18451. }
  18452. }
  18453. }
  18454. parser.parseOptionalKeyword('inclusive');
  18455. if (parser.parseOptionalKeyword('step')) {
  18456. if (parser.parseOptionalLParen()) {
  18457. const unresolvedStep = [];
  18458. while (parser.getToken().isNot(_.Token.r_paren)) {
  18459. unresolvedStep.push(parser.parseOperand());
  18460. if (!parser.parseOptionalComma()) {
  18461. break;
  18462. }
  18463. }
  18464. parser.parseRParen();
  18465. for (const step of unresolvedStep) {
  18466. parser.resolveOperand(step, null, result.operands);
  18467. }
  18468. }
  18469. }
  18470. }
  18471. if (parser.parseOptionalKeyword('collapse')) {
  18472. parser.parseLParen();
  18473. const value = parser.getToken().getSpelling().str();
  18474. parser.consumeToken(_.Token.integer);
  18475. result.addAttribute('collapse_num_loops', parseInt(value, 10));
  18476. parser.parseRParen();
  18477. }
  18478. if (parser.parseOptionalKeyword('tiles')) {
  18479. parser.parseLParen();
  18480. const tiles = [];
  18481. while (parser.getToken().isNot(_.Token.r_paren)) {
  18482. tiles.push(parseInt(parser.getToken().getSpelling().str(), 10));
  18483. parser.consumeToken(_.Token.integer);
  18484. if (!parser.parseOptionalComma()) {
  18485. break;
  18486. }
  18487. }
  18488. parser.parseRParen();
  18489. result.addAttribute('tile_sizes', tiles);
  18490. }
  18491. if (parser.getToken().is(_.Token.l_brace)) {
  18492. const region = result.addRegion();
  18493. parser.parseRegion(region);
  18494. }
  18495. parser.parseOptionalAttrDict(result.attributes);
  18496. return true;
  18497. }
  18498. parseMapBoundsOp(parser, result) {
  18499. // oilist(lower_bound(...) | upper_bound(...) | extent(...) | stride(...) | start_idx(...)) attr-dict
  18500. result.compatibility = true;
  18501. const operandSegmentSizes = [0, 0, 0, 0, 0]; // lower_bound, upper_bound, extent, stride, start_idx
  18502. const keywords = ['lower_bound', 'upper_bound', 'extent', 'stride', 'start_idx'];
  18503. while (true) {
  18504. let matched = false;
  18505. for (let i = 0; i < keywords.length; i++) {
  18506. if (parser.parseOptionalKeyword(keywords[i])) {
  18507. parser.parseLParen();
  18508. const operand = parser.parseOperand();
  18509. parser.parseColon();
  18510. const type = parser.parseType();
  18511. parser.resolveOperand(operand, type, result.operands);
  18512. parser.parseRParen();
  18513. operandSegmentSizes[i] = 1;
  18514. matched = true;
  18515. break;
  18516. }
  18517. }
  18518. if (!matched) {
  18519. break;
  18520. }
  18521. }
  18522. parser.parseOptionalAttrDict(result.attributes);
  18523. result.addAttribute('operandSegmentSizes', operandSegmentSizes);
  18524. result.addTypes([new _.Type('!omp.map_bounds_ty')]);
  18525. return true;
  18526. }
  18527. parseParenthesizedEnumAttr(parser) {
  18528. if (parser.parseOptionalLParen()) {
  18529. const value = parser.parseOptionalKeyword();
  18530. parser.parseRParen();
  18531. return new _.TypedAttr(value, null);
  18532. }
  18533. return null;
  18534. }
  18535. parseOrderClause(parser, result) {
  18536. const orderModifiers = ['reproducible', 'unconstrained'];
  18537. const orderKinds = ['concurrent'];
  18538. let orderMod = null;
  18539. let orderKind = null;
  18540. const keyword = parser.parseOptionalKeyword();
  18541. if (orderModifiers.includes(keyword)) {
  18542. orderMod = keyword;
  18543. parser.parseColon();
  18544. orderKind = parser.parseOptionalKeyword();
  18545. } else if (orderKinds.includes(keyword)) {
  18546. orderKind = keyword;
  18547. }
  18548. if (orderKind) {
  18549. result.addAttribute('order_kind', orderKind);
  18550. }
  18551. if (orderMod) {
  18552. result.addAttribute('order_mod', orderMod);
  18553. }
  18554. }
  18555. parseLinearClause(parser, result) {
  18556. const unresolvedLinearVars = [];
  18557. const linearVarTypes = [];
  18558. const unresolvedStepVars = [];
  18559. do {
  18560. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  18561. break;
  18562. }
  18563. unresolvedLinearVars.push(parser.parseOperand());
  18564. parser.parseEqual();
  18565. unresolvedStepVars.push(parser.parseOperand());
  18566. parser.parseColon();
  18567. const type = parser.parseType();
  18568. linearVarTypes.push(type);
  18569. } while (parser.parseOptionalComma());
  18570. parser.resolveOperands(unresolvedLinearVars, linearVarTypes, result.operands);
  18571. // Step vars typically have same type as linear vars
  18572. parser.resolveOperands(unresolvedStepVars, linearVarTypes, result.operands);
  18573. }
  18574. parseUniformClause(parser, result, uniformVars, uniformTypes) {
  18575. parser.parseCommaSeparatedList('none', () => {
  18576. uniformVars.push(parser.parseOperand());
  18577. parser.parseColon();
  18578. uniformTypes.push(parser.parseType());
  18579. });
  18580. }
  18581. parseCopyprivate(parser, op, varsAttr, typesAttr, symsAttr) {
  18582. const unresolvedVars = [];
  18583. const varTypes = [];
  18584. const copyprivateSyms = [];
  18585. do {
  18586. unresolvedVars.push(parser.parseOperand());
  18587. parser.parseArrow();
  18588. const sym = parser.getToken().getSpelling().str();
  18589. parser.consumeToken(_.Token.at_identifier);
  18590. parser.parseColon();
  18591. const type = parser.parseType();
  18592. varTypes.push(type);
  18593. copyprivateSyms.push(sym);
  18594. } while (parser.parseOptionalComma());
  18595. parser.resolveOperands(unresolvedVars, varTypes, op.operands);
  18596. if (symsAttr) {
  18597. op.addAttribute(symsAttr, copyprivateSyms);
  18598. }
  18599. }
  18600. parseGranularityClause(parser, op, modAttr) {
  18601. let modifier = null;
  18602. if (parser.getToken().is(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.percent_identifier)) {
  18603. modifier = parser.getToken().getSpelling().str();
  18604. parser.consumeToken(_.Token.bare_identifier);
  18605. parser.parseComma();
  18606. }
  18607. const unresolvedOperand = parser.parseOperand();
  18608. parser.parseColon();
  18609. const type = parser.parseType();
  18610. parser.resolveOperand(unresolvedOperand, type, op.operands);
  18611. if (modAttr && modifier) {
  18612. op.addAttribute(modAttr, modifier);
  18613. }
  18614. }
  18615. parseAlignedClause(parser, result) {
  18616. const unresolvedVars = [];
  18617. const varTypes = [];
  18618. const alignments = [];
  18619. do {
  18620. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  18621. break;
  18622. }
  18623. unresolvedVars.push(parser.parseOperand());
  18624. parser.parseColon();
  18625. const type = parser.parseType();
  18626. varTypes.push(type);
  18627. parser.parseArrow();
  18628. const alignment = parser.parseAttribute();
  18629. alignments.push(alignment);
  18630. } while (parser.parseOptionalComma());
  18631. parser.resolveOperands(unresolvedVars, varTypes, result.operands);
  18632. if (alignments.length > 0) {
  18633. result.addAttribute('alignments', alignments);
  18634. }
  18635. }
  18636. parseAffinityClause(parser, result, affinityVars, affinityTypes) {
  18637. parser.parseCommaSeparatedList('none', () => {
  18638. affinityVars.push(parser.parseOperand());
  18639. parser.parseColon();
  18640. affinityTypes.push(parser.parseType());
  18641. });
  18642. }
  18643. parseScheduleClause(parser, result) {
  18644. const scheduleKinds = ['static', 'dynamic', 'guided', 'auto', 'runtime', 'distribute'];
  18645. let scheduleKind = null;
  18646. for (const kind of scheduleKinds) {
  18647. if (parser.parseOptionalKeyword(kind)) {
  18648. scheduleKind = kind;
  18649. break;
  18650. }
  18651. }
  18652. if (scheduleKind) {
  18653. result.addAttribute('schedule_kind', scheduleKind);
  18654. }
  18655. if (parser.parseOptionalEqual()) {
  18656. let unresolvedChunk = null;
  18657. if (parser.getToken().is(_.Token.percent_identifier)) {
  18658. unresolvedChunk = parser.parseOperand();
  18659. }
  18660. if (parser.parseOptionalColon()) {
  18661. const type = parser.parseType();
  18662. if (unresolvedChunk) {
  18663. parser.resolveOperand(unresolvedChunk, type, result.operands);
  18664. }
  18665. } else if (unresolvedChunk) {
  18666. parser.resolveOperand(unresolvedChunk, null, result.operands);
  18667. }
  18668. }
  18669. const modifiers = [];
  18670. while (parser.parseOptionalComma()) {
  18671. const mod = parser.parseOptionalKeyword();
  18672. if (mod) {
  18673. modifiers.push(mod);
  18674. }
  18675. }
  18676. if (modifiers.length > 0) {
  18677. result.addAttribute('schedule_modifiers', modifiers);
  18678. }
  18679. }
  18680. parseAllocateAndAllocator(parser, result) {
  18681. const unresolvedAllocators = [];
  18682. const allocatorTypes = [];
  18683. const unresolvedAllocates = [];
  18684. const allocateTypes = [];
  18685. do {
  18686. if (parser.getToken().isNot(_.Token.percent_identifier)) {
  18687. break;
  18688. }
  18689. unresolvedAllocators.push(parser.parseOperand());
  18690. parser.parseColon();
  18691. allocatorTypes.push(parser.parseType());
  18692. parser.parseArrow();
  18693. unresolvedAllocates.push(parser.parseOperand());
  18694. parser.parseColon();
  18695. allocateTypes.push(parser.parseType());
  18696. } while (parser.parseOptionalComma());
  18697. parser.resolveOperands(unresolvedAllocators, allocatorTypes, result.operands);
  18698. parser.resolveOperands(unresolvedAllocates, allocateTypes, result.operands);
  18699. }
  18700. parseSynchronizationHint(parser, op, hintAttr = 'hint') {
  18701. if (parser.parseOptionalKeyword('none')) {
  18702. op.addAttribute(hintAttr, 0);
  18703. return;
  18704. }
  18705. let hint = 0;
  18706. const hints = [];
  18707. while (parser.getToken().is(_.Token.bare_identifier)) {
  18708. const keyword = parser.getToken().getSpelling().str();
  18709. parser.consumeToken(_.Token.bare_identifier);
  18710. hints.push(keyword);
  18711. if (keyword === 'uncontended') {
  18712. hint |= 1;
  18713. } else if (keyword === 'contended') {
  18714. hint |= 2;
  18715. } else if (keyword === 'nonspeculative') {
  18716. hint |= 4;
  18717. } else if (keyword === 'speculative') {
  18718. hint |= 8;
  18719. }
  18720. if (!parser.parseOptionalComma()) {
  18721. break;
  18722. }
  18723. }
  18724. op.addAttribute(hintAttr, hint);
  18725. }
  18726. parseClauseAttr(parser, op, attrName) {
  18727. // Parses a keyword (enum value) and converts to attribute
  18728. if (parser.getToken().is(_.Token.bare_identifier)) {
  18729. const enumValue = parser.getToken().getSpelling().str();
  18730. parser.consumeToken(_.Token.bare_identifier);
  18731. if (attrName) {
  18732. op.addAttribute(attrName, enumValue);
  18733. }
  18734. } else if (parser.getToken().is(_.Token.l_brace)) {
  18735. parser.skip('{');
  18736. }
  18737. }
  18738. parseTargetOpRegion(parser, result) {
  18739. const unitAttrKeywords = ['nowait', 'bare'];
  18740. for (const kw of unitAttrKeywords) {
  18741. if (parser.parseOptionalKeyword(kw)) {
  18742. result.addAttribute(kw, true);
  18743. }
  18744. }
  18745. if (parser.parseOptionalKeyword('depend')) {
  18746. parser.skip('(');
  18747. }
  18748. const singleValueKeywords = ['device', 'if', 'thread_limit'];
  18749. for (const kw of singleValueKeywords) {
  18750. if (parser.parseOptionalKeyword(kw)) {
  18751. parser.parseLParen();
  18752. if (parser.getToken().is(_.Token.percent_identifier)) {
  18753. const unresolvedOperand = parser.parseOperand();
  18754. let opType = null;
  18755. if (parser.parseOptionalColon()) {
  18756. opType = parser.parseType();
  18757. }
  18758. parser.resolveOperand(unresolvedOperand, opType, result.operands);
  18759. } else if (parser.parseOptionalColon()) {
  18760. parser.parseType();
  18761. }
  18762. parser.parseRParen();
  18763. }
  18764. }
  18765. if (parser.parseOptionalKeyword('is_device_ptr')) {
  18766. parser.parseLParen();
  18767. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  18768. if (parser.getToken().is(_.Token.percent_identifier)) {
  18769. parser.parseOperand();
  18770. }
  18771. if (!parser.parseOptionalComma()) {
  18772. break;
  18773. }
  18774. }
  18775. if (parser.parseOptionalColon()) {
  18776. while (parser.getToken().isNot(_.Token.r_paren)) {
  18777. parser.parseType();
  18778. if (!parser.parseOptionalComma()) {
  18779. break;
  18780. }
  18781. }
  18782. }
  18783. parser.parseRParen();
  18784. }
  18785. const keywords = ['has_device_addr', 'host_eval', 'in_reduction', 'map_entries', 'private', 'reduction', 'task_reduction', 'use_device_addr', 'use_device_ptr'];
  18786. let progress = true;
  18787. while (progress) {
  18788. progress = false;
  18789. // Handle private_barrier unit attribute
  18790. if (parser.parseOptionalKeyword('private_barrier')) {
  18791. result.addAttribute('private_needs_barrier', true);
  18792. progress = true;
  18793. continue;
  18794. }
  18795. // Handle list clauses
  18796. if (keywords.some((kw) => parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === kw)) {
  18797. parser.consumeToken(_.Token.bare_identifier);
  18798. progress = true;
  18799. if (parser.parseOptionalLParen()) {
  18800. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  18801. parser.parseOptionalKeyword('byref');
  18802. if (parser.getToken().is(_.Token.at_identifier)) {
  18803. parser.consumeToken(_.Token.at_identifier);
  18804. }
  18805. if (parser.getToken().is(_.Token.percent_identifier)) {
  18806. parser.parseOperand();
  18807. }
  18808. if (parser.parseOptionalArrow()) {
  18809. if (parser.getToken().is(_.Token.percent_identifier)) {
  18810. parser.parseOperand();
  18811. }
  18812. }
  18813. if (parser.parseOptionalLSquare()) {
  18814. parser.parseKeyword('map_idx');
  18815. parser.parseEqual();
  18816. parser.consumeToken(_.Token.integer);
  18817. parser.parseRSquare();
  18818. }
  18819. if (!parser.parseOptionalComma() || parser.getToken().is(_.Token.colon)) {
  18820. break;
  18821. }
  18822. }
  18823. if (parser.parseOptionalColon()) {
  18824. while (parser.getToken().isNot(_.Token.r_paren)) {
  18825. parser.parseType();
  18826. if (!parser.parseOptionalComma()) {
  18827. break;
  18828. }
  18829. }
  18830. }
  18831. parser.parseRParen();
  18832. }
  18833. }
  18834. }
  18835. if (parser.getToken().isNot(_.Token.l_brace)) {
  18836. return;
  18837. }
  18838. const region = {};
  18839. parser.parseRegion(region);
  18840. result.regions.push(region);
  18841. }
  18842. parseMapClause(parser, op, attrName = 'map_type') {
  18843. const mapFlags = [];
  18844. do {
  18845. if (parser.getToken().is(_.Token.bare_identifier)) {
  18846. const flag = parser.getToken().getSpelling().str();
  18847. parser.consumeToken(_.Token.bare_identifier);
  18848. mapFlags.push(flag);
  18849. }
  18850. } while (parser.parseOptionalComma());
  18851. if (attrName && mapFlags.length > 0) {
  18852. op.addAttribute(attrName, mapFlags.join(', '));
  18853. }
  18854. }
  18855. parseCaptureType(parser, op, attrName) {
  18856. if (parser.getToken().is(_.Token.bare_identifier)) {
  18857. const captureType = parser.getToken().getSpelling().str();
  18858. parser.consumeToken(_.Token.bare_identifier);
  18859. if (attrName) {
  18860. op.addAttribute(attrName, captureType);
  18861. }
  18862. }
  18863. }
  18864. parseMembersIndex(parser, op, attrName) {
  18865. const memberIndices = [];
  18866. do {
  18867. if (parser.parseOptionalLSquare()) {
  18868. const indices = [];
  18869. do {
  18870. if (parser.getToken().is(_.Token.integer)) {
  18871. const idx = parser.getToken().getSpelling().str();
  18872. parser.consumeToken(_.Token.integer);
  18873. indices.push(idx);
  18874. }
  18875. } while (parser.parseOptionalComma());
  18876. parser.parseRSquare();
  18877. memberIndices.push(indices);
  18878. }
  18879. } while (parser.parseOptionalComma());
  18880. if (attrName && memberIndices.length > 0) {
  18881. op.addAttribute(attrName, memberIndices);
  18882. }
  18883. }
  18884. parsePrivateReductionRegion(parser, result) {
  18885. const singleValueClauses = ['if', 'num_threads', 'thread_limit', 'device', 'safelen', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'final', 'filter'];
  18886. const enumClauses = ['proc_bind', 'order', 'schedule', 'dist_schedule', 'memory_order', 'hint'];
  18887. const listClauses = ['private', 'reduction', 'in_reduction', 'task_reduction', 'copyin', 'copyprivate', 'firstprivate', 'lastprivate', 'shared', 'linear', 'aligned', 'nontemporal', 'inclusive', 'exclusive', 'allocate', 'depend'];
  18888. const unitClauses = ['nowait', 'untied', 'mergeable', 'nogroup', 'simd', 'threads', 'seq_cst', 'acq_rel', 'acquire', 'release', 'relaxed', 'private_barrier'];
  18889. let progress = true;
  18890. while (progress) {
  18891. progress = false;
  18892. // Handle single-value clauses: keyword(value : type)
  18893. for (const kw of singleValueClauses) {
  18894. if (parser.parseOptionalKeyword(kw)) {
  18895. progress = true;
  18896. parser.parseLParen();
  18897. let unresolvedOp = null;
  18898. let opType = null;
  18899. if (parser.getToken().is(_.Token.percent_identifier)) {
  18900. unresolvedOp = parser.parseOperand();
  18901. } else if (parser.getToken().is(_.Token.integer)) {
  18902. const value = parser.getToken().getSpelling().str();
  18903. parser.consumeToken(_.Token.integer);
  18904. result.addAttribute(kw, value);
  18905. }
  18906. if (parser.parseOptionalColon()) {
  18907. opType = parser.parseType();
  18908. }
  18909. if (unresolvedOp) {
  18910. parser.resolveOperand(unresolvedOp, opType, result.operands);
  18911. }
  18912. parser.parseRParen();
  18913. }
  18914. }
  18915. // Handle enum clauses: keyword(enum_value)
  18916. for (const kw of enumClauses) {
  18917. if (parser.parseOptionalKeyword(kw)) {
  18918. progress = true;
  18919. parser.parseLParen();
  18920. const value = parser.getToken().getSpelling().str();
  18921. parser.consumeToken(_.Token.bare_identifier);
  18922. result.addAttribute(kw, value);
  18923. // Handle modifier syntax like schedule(static, value)
  18924. while (parser.parseOptionalComma()) {
  18925. if (parser.getToken().is(_.Token.percent_identifier)) {
  18926. const unresolvedOp = parser.parseOperand();
  18927. let opType = null;
  18928. if (parser.parseOptionalColon()) {
  18929. opType = parser.parseType();
  18930. }
  18931. parser.resolveOperand(unresolvedOp, opType, result.operands);
  18932. } else if (parser.getToken().is(_.Token.bare_identifier)) {
  18933. parser.consumeToken(_.Token.bare_identifier);
  18934. if (parser.parseOptionalColon()) {
  18935. parser.parseType();
  18936. }
  18937. }
  18938. }
  18939. parser.parseRParen();
  18940. }
  18941. }
  18942. // Handle list clauses: keyword(syms %vals -> %new_vals : types) or keyword(@sym %val : type, ...)
  18943. for (const kw of listClauses) {
  18944. if (parser.parseOptionalKeyword(kw)) {
  18945. progress = true;
  18946. if (parser.parseOptionalLParen()) {
  18947. if (parser.consumeIf(_.Token.kw_mod)) {
  18948. parser.parseColon();
  18949. parser.consumeToken(_.Token.bare_identifier);
  18950. parser.parseComma();
  18951. }
  18952. const unresolvedOperands = [];
  18953. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  18954. parser.parseOptionalKeyword('byref');
  18955. if (parser.getToken().is(_.Token.at_identifier)) {
  18956. parser.consumeToken(_.Token.at_identifier);
  18957. }
  18958. if (parser.getToken().is(_.Token.percent_identifier)) {
  18959. unresolvedOperands.push(parser.parseOperand());
  18960. }
  18961. if (parser.parseOptionalArrow()) {
  18962. if (parser.getToken().is(_.Token.percent_identifier)) {
  18963. parser.parseOperand();
  18964. }
  18965. }
  18966. if (parser.parseOptionalLSquare()) {
  18967. parser.parseKeyword('map_idx');
  18968. parser.parseEqual();
  18969. parser.consumeToken(_.Token.integer);
  18970. parser.parseRSquare();
  18971. }
  18972. if (!parser.parseOptionalComma() || parser.getToken().is(_.Token.colon)) {
  18973. break;
  18974. }
  18975. }
  18976. const types = [];
  18977. if (parser.parseOptionalColon()) {
  18978. while (parser.getToken().isNot(_.Token.r_paren)) {
  18979. types.push(parser.parseType());
  18980. if (!parser.parseOptionalComma()) {
  18981. break;
  18982. }
  18983. }
  18984. }
  18985. parser.resolveOperands(unresolvedOperands, types, result.operands);
  18986. parser.parseRParen();
  18987. }
  18988. }
  18989. }
  18990. // Handle unit clauses (boolean flags)
  18991. for (const kw of unitClauses) {
  18992. if (parser.parseOptionalKeyword(kw)) {
  18993. progress = true;
  18994. // private_barrier maps to private_needs_barrier attribute
  18995. const attrName = kw === 'private_barrier' ? 'private_needs_barrier' : kw;
  18996. result.addAttribute(attrName, true);
  18997. }
  18998. }
  18999. // Handle map_entries clause: map_entries(%vars : types)
  19000. if (parser.parseOptionalKeyword('map_entries')) {
  19001. progress = true;
  19002. parser.parseLParen();
  19003. const unresolvedMapVars = [];
  19004. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  19005. if (parser.getToken().is(_.Token.percent_identifier)) {
  19006. const operand = parser.parseOperand();
  19007. unresolvedMapVars.push(operand);
  19008. }
  19009. if (!parser.parseOptionalComma() || parser.getToken().is(_.Token.colon)) {
  19010. break;
  19011. }
  19012. }
  19013. const mapTypes = [];
  19014. if (parser.parseOptionalColon()) {
  19015. while (parser.getToken().isNot(_.Token.r_paren)) {
  19016. mapTypes.push(parser.parseType());
  19017. if (!parser.parseOptionalComma()) {
  19018. break;
  19019. }
  19020. }
  19021. }
  19022. for (let i = 0; i < unresolvedMapVars.length; i++) {
  19023. const type = i < mapTypes.length ? mapTypes[i] : null;
  19024. parser.resolveOperand(unresolvedMapVars[i], type, result.operands);
  19025. }
  19026. parser.parseRParen();
  19027. }
  19028. // Handle num_teams clause: num_teams(lower : type to upper : type) or num_teams(to upper : type)
  19029. if (parser.parseOptionalKeyword('num_teams')) {
  19030. progress = true;
  19031. parser.parseLParen();
  19032. if (parser.parseOptionalKeyword('to')) {
  19033. if (parser.getToken().is(_.Token.percent_identifier)) {
  19034. const upper = parser.parseOperand();
  19035. let upperType = null;
  19036. if (parser.parseOptionalColon()) {
  19037. upperType = parser.parseType();
  19038. }
  19039. parser.resolveOperand(upper, upperType, result.operands);
  19040. }
  19041. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  19042. const lower = parser.parseOperand();
  19043. let lowerType = null;
  19044. if (parser.parseOptionalColon()) {
  19045. lowerType = parser.parseType();
  19046. }
  19047. parser.resolveOperand(lower, lowerType, result.operands);
  19048. parser.parseKeyword('to');
  19049. if (parser.getToken().is(_.Token.percent_identifier)) {
  19050. const upper = parser.parseOperand();
  19051. let upperType = null;
  19052. if (parser.parseOptionalColon()) {
  19053. upperType = parser.parseType();
  19054. }
  19055. parser.resolveOperand(upper, upperType, result.operands);
  19056. }
  19057. }
  19058. parser.parseRParen();
  19059. }
  19060. // Handle use_device_addr/use_device_ptr clauses: keyword(%var -> %arg : type, ...)
  19061. for (const kw of ['use_device_addr', 'use_device_ptr', 'has_device_addr', 'host_eval']) {
  19062. if (parser.parseOptionalKeyword(kw)) {
  19063. progress = true;
  19064. parser.parseLParen();
  19065. const unresolvedOperands = [];
  19066. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  19067. if (parser.getToken().is(_.Token.percent_identifier)) {
  19068. const operand = parser.parseOperand();
  19069. unresolvedOperands.push(operand);
  19070. }
  19071. if (parser.parseOptionalArrow()) {
  19072. if (parser.getToken().is(_.Token.percent_identifier)) {
  19073. parser.parseOperand();
  19074. }
  19075. }
  19076. if (!parser.parseOptionalComma() || parser.getToken().is(_.Token.colon)) {
  19077. break;
  19078. }
  19079. }
  19080. const types = [];
  19081. if (parser.parseOptionalColon()) {
  19082. while (parser.getToken().isNot(_.Token.r_paren)) {
  19083. types.push(parser.parseType());
  19084. if (!parser.parseOptionalComma()) {
  19085. break;
  19086. }
  19087. }
  19088. }
  19089. for (let i = 0; i < unresolvedOperands.length; i++) {
  19090. const type = i < types.length ? types[i] : null;
  19091. parser.resolveOperand(unresolvedOperands[i], type, result.operands);
  19092. }
  19093. parser.parseRParen();
  19094. }
  19095. }
  19096. }
  19097. if (parser.getToken().is(_.Token.l_brace)) {
  19098. const region = {};
  19099. parser.parseRegion(region);
  19100. result.regions.push(region);
  19101. }
  19102. }
  19103. parseDataSharingClauseTypeAttr(parser) {
  19104. if (parser.parseOptionalLBrace()) {
  19105. parser.parseKeyword('type');
  19106. parser.parseEqual();
  19107. const value = parser.getToken().getSpelling().str();
  19108. parser.consumeToken(_.Token.bare_identifier);
  19109. parser.parseRBrace();
  19110. return { value };
  19111. }
  19112. return null;
  19113. }
  19114. parseDependVarList(parser, op, operandAttr, typesAttr, kindAttr) {
  19115. const dependVars = [];
  19116. const dependTypes = [];
  19117. const dependKinds = [];
  19118. do {
  19119. const keyword = parser.getToken().getSpelling().str();
  19120. parser.consumeToken(_.Token.bare_identifier);
  19121. dependKinds.push(keyword);
  19122. parser.parseArrow();
  19123. const operand = parser.parseOperand();
  19124. dependVars.push(operand);
  19125. parser.parseColon();
  19126. const type = parser.parseType();
  19127. dependTypes.push(type);
  19128. } while (parser.parseOptionalComma());
  19129. if (operandAttr) {
  19130. // depend_vars are SSA operands - resolve and add as operands
  19131. for (let i = 0; i < dependVars.length; i++) {
  19132. const type = i < dependTypes.length ? dependTypes[i] : null;
  19133. parser.resolveOperand(dependVars[i], type, op.operands);
  19134. }
  19135. }
  19136. if (kindAttr) {
  19137. op.addAttribute(kindAttr, dependKinds);
  19138. }
  19139. }
  19140. // Syntax 1: (generatees) <- (applyees) - generatees present (no leading <)
  19141. // Syntax 2: <- (applyees) - generatees omitted (starts with <-)
  19142. parseLoopTransformClis(parser, result) {
  19143. const generatees = [];
  19144. const applyees = [];
  19145. if (!parser.parseOptionalLess()) {
  19146. // Syntax 1: generatees present, parse (generatees) first
  19147. parser.parseLParen();
  19148. while (parser.getToken().isNot(_.Token.r_paren)) {
  19149. if (parser.getToken().is(_.Token.percent_identifier)) {
  19150. generatees.push(parser.parseOperand());
  19151. }
  19152. if (!parser.parseOptionalComma()) {
  19153. break;
  19154. }
  19155. }
  19156. parser.parseRParen();
  19157. parser.parseLess();
  19158. }
  19159. parser.consumeToken(_.Token.minus);
  19160. parser.parseLParen();
  19161. while (parser.getToken().isNot(_.Token.r_paren)) {
  19162. if (parser.getToken().is(_.Token.percent_identifier)) {
  19163. applyees.push(parser.parseOperand());
  19164. }
  19165. if (!parser.parseOptionalComma()) {
  19166. break;
  19167. }
  19168. }
  19169. parser.parseRParen();
  19170. for (const g of generatees) {
  19171. parser.resolveOperand(g, null, result.operands);
  19172. }
  19173. for (const a of applyees) {
  19174. parser.resolveOperand(a, null, result.operands);
  19175. }
  19176. }
  19177. };
  19178. _.LLVM = {};
  19179. _.LLVM.LLVMFunctionType = class extends _.Type {
  19180. constructor(returnType, params, varArg = false) {
  19181. super(null);
  19182. this.returnType = returnType;
  19183. this.params = params || [];
  19184. this.varArg = varArg;
  19185. }
  19186. get inputs() {
  19187. return this.params;
  19188. }
  19189. get results() {
  19190. return this.returnType ? [this.returnType] : [];
  19191. }
  19192. toString() {
  19193. const params = this.params.map((t) => t.toString());
  19194. if (this.varArg) {
  19195. params.push('...');
  19196. }
  19197. const returnType = this.returnType ? this.returnType.toString() : 'void';
  19198. return `!llvm.func<${returnType} (${params.join(', ')})>`;
  19199. }
  19200. };
  19201. _.LLVM.LLVMDialect = class extends _.Dialect {
  19202. constructor(operations, name = 'llvm') {
  19203. super(operations, name);
  19204. this.registerCustomDirective('GEPIndices', this.parseGEPIndices.bind(this));
  19205. this.registerCustomDirective('IndirectBrOpSucessors', this.parseIndirectBrOpSucessors.bind(this));
  19206. this.registerCustomDirective('InsertExtractValueElementType', this.parseInsertExtractValueElementType.bind(this));
  19207. this.registerCustomDirective('LLVMLinkage', this.parseLLVMLinkage.bind(this));
  19208. this.registerCustomDirective('OpBundles', this.parseOpBundles.bind(this));
  19209. this.registerCustomDirective('ShuffleType', this.parseShuffleType.bind(this));
  19210. this.registerCustomDirective('SwitchOpCases', this.parseSwitchOpCases.bind(this));
  19211. this.registerCustomAttribute('LLVM_IntegerOverflowFlagsProp', this.parseLLVMIntegerOverflowFlagsProp.bind(this));
  19212. this.registerCustomAttribute('GEPNoWrapFlagsProp', this.parseGEPNoWrapFlagsProp.bind(this));
  19213. this.registerCustomAttribute('LLVM_BlockAddressAttr', this.parseLLVMBlockAddressAttr.bind(this));
  19214. this.registerCustomAttribute('LLVM_BlockTagAttr', this.parseLLVMBlockTagAttr.bind(this));
  19215. this.registerCustomType('LLVM_AnyPointer', this.parseLLVMPointerType.bind(this));
  19216. this.registerCustomType('LLVM_PointerInAddressSpace', this.parseLLVMPointerType.bind(this));
  19217. this.registerCustomType('LLVM_Type', (parser) => parser.parseType());
  19218. }
  19219. parseLLVMIntegerOverflowFlagsProp(parser) {
  19220. if (parser.parseOptionalKeyword('overflow')) {
  19221. return this.parseEnumFlagsAngleBracketComma(parser, { values: ['wrap', 'nuw', 'nsw'] });
  19222. }
  19223. return null;
  19224. }
  19225. parseGEPNoWrapFlagsProp(parser, type) {
  19226. if (type.values.includes(parser.getTokenSpelling().str())) {
  19227. return this.parseEnumFlags(parser, type, '|');
  19228. }
  19229. return null;
  19230. }
  19231. parseLLVMBlockAddressAttr(parser) {
  19232. if (parser.getToken().isNot(_.Token.less)) {
  19233. return null;
  19234. }
  19235. const content = parser.skip('<');
  19236. return { blockaddress: content };
  19237. }
  19238. parseLLVMBlockTagAttr(parser) {
  19239. if (parser.getToken().isNot(_.Token.less)) {
  19240. return null;
  19241. }
  19242. const content = parser.skip('<');
  19243. return { blocktag: content };
  19244. }
  19245. parseLLVMPointerType(parser) {
  19246. if (parser.getToken().is(_.Token.less)) {
  19247. const content = parser.skip('<');
  19248. const inner = content.startsWith('<') && content.endsWith('>') ? content.slice(1, -1) : content;
  19249. if (/^\d+$/.test(inner)) {
  19250. return new _.Type(`!llvm.ptr<${inner}>`);
  19251. }
  19252. }
  19253. return parser.parseType();
  19254. }
  19255. getInsertExtractValueElementType(containerType, position) {
  19256. let llvmType = containerType.toString ? containerType.toString() : String(containerType);
  19257. for (const idx of position) {
  19258. const arrayMatch = llvmType.match(/^!llvm\.array<(\d+)\s*x\s*(.+)>$/);
  19259. if (arrayMatch) {
  19260. llvmType = arrayMatch[2].trim();
  19261. continue;
  19262. }
  19263. const structMatch = llvmType.match(/^!llvm\.struct<(?:"[^"]*",\s*)?\((.+)\)>$/);
  19264. if (structMatch) {
  19265. const elementsStr = structMatch[1];
  19266. const body = [];
  19267. let depth = 0;
  19268. let current = '';
  19269. for (const char of elementsStr) {
  19270. if (char === '<' || char === '(' || char === '[' || char === '{') {
  19271. depth++;
  19272. current += char;
  19273. } else if (char === '>' || char === ')' || char === ']' || char === '}') {
  19274. depth--;
  19275. current += char;
  19276. } else if (char === ',' && depth === 0) {
  19277. body.push(current.trim());
  19278. current = '';
  19279. } else {
  19280. current += char;
  19281. }
  19282. }
  19283. if (current.trim()) {
  19284. body.push(current.trim());
  19285. }
  19286. if (idx >= 0 && idx < body.length) {
  19287. llvmType = body[idx];
  19288. continue;
  19289. }
  19290. }
  19291. break;
  19292. }
  19293. return llvmType;
  19294. }
  19295. parseInsertExtractValueElementType(parser, op, resultTypes, containerTypes, positionArg) {
  19296. // Infer the value type from the container type and position.
  19297. // resultTypes = op.types (array to populate)
  19298. // containerTypes = array of container types from parsing
  19299. // positionArg = position attribute value (ArrayAttr or array)
  19300. if (containerTypes && containerTypes.length > 0) {
  19301. const containerType = containerTypes[0];
  19302. // Use the position argument if provided, otherwise fall back to op.attributes
  19303. const positionAttr = positionArg === undefined ? op.attributes.get('position') : positionArg;
  19304. const position = positionAttr && positionAttr.value ? positionAttr.value : positionAttr;
  19305. if (position && Array.isArray(position) && position.length > 0) {
  19306. const valueType = this.getInsertExtractValueElementType(containerType, position);
  19307. if (valueType && resultTypes.length === 0) {
  19308. resultTypes.push(new _.Type(valueType));
  19309. }
  19310. }
  19311. }
  19312. }
  19313. parseLLVMLinkage(parser, op /*, args */) {
  19314. if (parser.getToken().is(_.Token.bare_identifier)) {
  19315. const linkage = parser.getToken().getSpelling().str();
  19316. parser.consumeToken(_.Token.bare_identifier);
  19317. op.addAttribute('linkage', linkage);
  19318. }
  19319. }
  19320. parseOpBundles(parser, op /*, args */) {
  19321. // Parse operation bundles: [] or ["tag"()] or ["tag"(%0, %1 : i32, i32), ...]
  19322. // Returns: null if not present, true if success, throws on failure
  19323. // args[0] = $op_bundle_operands - operands for bundles
  19324. // args[1] = type($op_bundle_operands) - types
  19325. // args[2] = $op_bundle_tags - tags attribute
  19326. if (!parser.parseOptionalLSquare()) {
  19327. return null; // Not present (equivalent to std::nullopt)
  19328. }
  19329. if (parser.parseOptionalRSquare()) {
  19330. return true; // Success
  19331. }
  19332. const opBundles = [];
  19333. do {
  19334. const tag = parser.getToken().getSpelling().str();
  19335. parser.consumeToken(_.Token.string);
  19336. parser.parseLParen();
  19337. const bundleOperands = [];
  19338. if (parser.getToken().isNot(_.Token.r_paren)) {
  19339. do {
  19340. bundleOperands.push(parser.parseAttribute());
  19341. } while (parser.parseOptionalComma());
  19342. parser.parseColon();
  19343. do {
  19344. parser.parseType();
  19345. } while (parser.parseOptionalComma());
  19346. }
  19347. parser.parseRParen();
  19348. opBundles.push({ tag, operands: bundleOperands });
  19349. } while (parser.parseOptionalComma());
  19350. parser.parseRSquare();
  19351. if (opBundles.length > 0) {
  19352. op.addAttribute('op_bundle_tags', opBundles);
  19353. }
  19354. return true; // Success
  19355. }
  19356. parseShuffleType(parser, op, v1Types, resTypes, maskAttr) {
  19357. // custom<ShuffleType>(ref(type($v1)), type($res), ref($mask))
  19358. // Computes the result type: same element type as input, length = mask.size()
  19359. if (resTypes.length > 0) {
  19360. return; // Result type already set
  19361. }
  19362. if (!v1Types || v1Types.length === 0 || !maskAttr) {
  19363. return;
  19364. }
  19365. const v1Type = v1Types[0];
  19366. const typeStr = v1Type.toString ? v1Type.toString() : String(v1Type);
  19367. const vecMatch = typeStr.match(/^vector<(?:\[)?(\d+)(?:\])?\s*x\s*(.+)>$/);
  19368. if (!vecMatch) {
  19369. return;
  19370. }
  19371. const elemType = vecMatch[2];
  19372. const isScalable = typeStr.includes('[') && typeStr.includes(']');
  19373. // Get mask length
  19374. let maskLen = 0;
  19375. const mask = maskAttr.value === undefined ? maskAttr : maskAttr.value;
  19376. if (Array.isArray(mask)) {
  19377. maskLen = mask.length;
  19378. } else if (typeof mask === 'string') {
  19379. const stripped = mask.replace(/[[\]]/g, '').trim();
  19380. if (stripped) {
  19381. maskLen = stripped.split(',').length;
  19382. }
  19383. }
  19384. if (maskLen > 0) {
  19385. const resultTypeStr = isScalable ?
  19386. `vector<[${maskLen}]x${elemType}>` :
  19387. `vector<${maskLen}x${elemType}>`;
  19388. op.addTypes([new _.Type(resultTypeStr)]);
  19389. }
  19390. }
  19391. // Parse switch operation cases
  19392. // Where case: integer `:` bb-id (`(` ssa-use-and-type-list `)`)?
  19393. parseSwitchOpCases(parser, op /*, args */) {
  19394. // args[0] is ref(type($value)) - the flag type
  19395. // args[1] is $case_values - attribute to populate
  19396. // args[2] is $caseDestinations - successors array
  19397. // args[3] is $caseOperands - operands for each case
  19398. // args[4] is type($caseOperands) - types for case operands
  19399. if (!parser.parseOptionalLSquare()) {
  19400. return;
  19401. }
  19402. if (parser.parseOptionalRSquare()) {
  19403. return;
  19404. }
  19405. const caseValues = [];
  19406. const caseDestinations = [];
  19407. const caseOperands = [];
  19408. while (parser.getToken().isNot(_.Token.r_square) && parser.getToken().isNot(_.Token.eof)) {
  19409. // Handle negative case values: -1, -2, etc.
  19410. let sign = 1;
  19411. if (parser.consumeIf(_.Token.minus)) {
  19412. sign = -1;
  19413. }
  19414. if (parser.getToken().isNot(_.Token.integer) && parser.getToken().isNot('number')) {
  19415. throw new mlir.Error(`Expected integer case value at ${parser.location()}`);
  19416. }
  19417. const value = sign * parseInt(parser.getToken().getSpelling().str(), 10);
  19418. parser.consumeToken();
  19419. caseValues.push(value);
  19420. parser.parseColon();
  19421. const successor = parser.getToken().getSpelling().str();
  19422. parser.consumeToken(_.Token.caret_identifier);
  19423. caseDestinations.push(successor);
  19424. if (parser.parseOptionalLParen()) {
  19425. const operands = [];
  19426. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.eof)) {
  19427. if (parser.getToken().is(_.Token.percent_identifier)) {
  19428. const operand = parser.parseOperand();
  19429. operands.push({ name: operand });
  19430. if (!parser.parseOptionalComma()) {
  19431. break;
  19432. }
  19433. } else {
  19434. break;
  19435. }
  19436. }
  19437. if (parser.parseOptionalColon()) {
  19438. let idx = 0;
  19439. while (parser.getToken().isNot(_.Token.r_paren) && idx < operands.length) {
  19440. const type = parser.parseType();
  19441. if (operands[idx]) {
  19442. operands[idx].type = type;
  19443. }
  19444. idx++;
  19445. parser.parseOptionalComma();
  19446. }
  19447. }
  19448. parser.parseRParen();
  19449. caseOperands.push(operands);
  19450. } else {
  19451. caseOperands.push([]);
  19452. }
  19453. if (!parser.parseOptionalComma()) {
  19454. break;
  19455. }
  19456. }
  19457. parser.parseRSquare();
  19458. if (caseValues.length > 0) {
  19459. op.addAttribute('case_values', caseValues);
  19460. }
  19461. if (caseDestinations.length > 0) {
  19462. if (!op.successors) {
  19463. op.successors = [];
  19464. }
  19465. for (const dest of caseDestinations) {
  19466. op.successors.push({ name: dest });
  19467. }
  19468. }
  19469. // Note: caseOperands handling would require more complex logic
  19470. // to properly associate operands with their successors
  19471. }
  19472. parseType(parser, dialect) {
  19473. const typeName = parser.parseOptionalKeyword();
  19474. if (!typeName) {
  19475. return null;
  19476. }
  19477. let type = `!${dialect}.${typeName}`;
  19478. if (parser.getToken().is(_.Token.less)) {
  19479. const content = parser.skip('<');
  19480. type += content;
  19481. }
  19482. return new _.Type(type);
  19483. }
  19484. parseOperation(parser, result) {
  19485. const opInfo = result.name.getRegisteredInfo();
  19486. if (result.op === 'llvm.func') {
  19487. return this.parseLLVMFuncOp(parser, result);
  19488. }
  19489. if (result.op === 'llvm.mlir.global') {
  19490. return this.parseLLVMGlobalOp(parser, result);
  19491. }
  19492. if (result.op === 'llvm.mlir.alias') {
  19493. return this.parseLLVMAliasOp(parser, result);
  19494. }
  19495. if (result.op === 'llvm.alloca') {
  19496. return this.parseLLVMAllocaOp(parser, result);
  19497. }
  19498. if (result.op === 'llvm.call') {
  19499. return this.parseLLVMCallOp(parser, result);
  19500. }
  19501. if (result.op === 'llvm.call_intrinsic') {
  19502. return this.parseLLVMCallIntrinsicOp(parser, result);
  19503. }
  19504. if (result.op === 'llvm.invoke') {
  19505. return this.parseLLVMInvokeOp(parser, result);
  19506. }
  19507. if (result.op === 'llvm.landingpad') {
  19508. return this.parseLLVMLandingpadOp(parser, result);
  19509. }
  19510. if (result.op === 'llvm.icmp' || result.op === 'llvm.fcmp') {
  19511. return this.parseLLVMCmpOp(parser, result);
  19512. }
  19513. if (result.op.startsWith('llvm.intr.')) {
  19514. if (opInfo.metadata.assemblyFormat) {
  19515. return super.parseOperation(parser, result);
  19516. }
  19517. return this.parseLLVMIntrinsicOp(parser, result);
  19518. }
  19519. return super.parseOperation(parser, result);
  19520. }
  19521. parseLLVMGlobalOp(parser, result) {
  19522. const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'appending', 'internal', 'private', 'extern_weak', 'common'];
  19523. if (parser.getToken().is(_.Token.bare_identifier) && linkageKeywords.includes(parser.getTokenSpelling().str())) {
  19524. const __spelling = parser.getToken().getSpelling().str();
  19525. parser.consumeToken(_.Token.bare_identifier);
  19526. result.addAttribute('linkage', __spelling);
  19527. }
  19528. const visibilityKeywords = ['default', 'hidden', 'protected'];
  19529. if (parser.getToken().is(_.Token.bare_identifier) && visibilityKeywords.includes(parser.getTokenSpelling().str())) {
  19530. const __spelling = parser.getToken().getSpelling().str();
  19531. parser.consumeToken(_.Token.bare_identifier);
  19532. result.addAttribute('visibility_', __spelling);
  19533. }
  19534. if (parser.parseOptionalKeyword('thread_local')) {
  19535. result.addAttribute('thread_local_', true);
  19536. }
  19537. const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];
  19538. if (parser.getToken().is(_.Token.bare_identifier) && unnamedAddrKeywords.includes(parser.getTokenSpelling().str())) {
  19539. const __spelling = parser.getToken().getSpelling().str();
  19540. parser.consumeToken(_.Token.bare_identifier);
  19541. result.addAttribute('unnamed_addr', __spelling);
  19542. }
  19543. if (parser.parseOptionalKeyword('constant')) {
  19544. result.addAttribute('constant', true);
  19545. }
  19546. if (parser.getToken().is(_.Token.at_identifier)) {
  19547. parser.parseSymbolName('sym_name', result.attributes);
  19548. }
  19549. parser.parseLParen();
  19550. if (parser.getToken().isNot(_.Token.r_paren)) {
  19551. const value = parser.parseAttribute();
  19552. if (parser.parseOptionalColon()) {
  19553. parser.parseType();
  19554. }
  19555. result.addAttribute('value', value);
  19556. }
  19557. parser.parseRParen();
  19558. if (parser.parseOptionalKeyword('comdat')) {
  19559. parser.parseLParen();
  19560. const comdat = parser.getToken().getSpelling().str();
  19561. parser.consumeToken(_.Token.at_identifier);
  19562. parser.parseRParen();
  19563. result.addAttribute('comdat', comdat);
  19564. }
  19565. if (parser.getToken().is(_.Token.l_brace)) {
  19566. parser.parseAttributeDict(result.attributes);
  19567. }
  19568. if (parser.parseOptionalColon()) {
  19569. const type = parser.parseType();
  19570. result.types = [type];
  19571. }
  19572. if (parser.getToken().is(_.Token.l_brace)) {
  19573. const region = result.addRegion();
  19574. parser.parseRegion(region);
  19575. }
  19576. return true;
  19577. }
  19578. parseLLVMAliasOp(parser, result) {
  19579. const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'internal', 'private'];
  19580. if (parser.getToken().is(_.Token.bare_identifier) && linkageKeywords.includes(parser.getTokenSpelling().str())) {
  19581. const __spelling = parser.getToken().getSpelling().str();
  19582. parser.consumeToken(_.Token.bare_identifier);
  19583. result.addAttribute('linkage', __spelling);
  19584. }
  19585. const visibilityKeywords = ['default', 'hidden', 'protected'];
  19586. if (parser.getToken().is(_.Token.bare_identifier) && visibilityKeywords.includes(parser.getTokenSpelling().str())) {
  19587. const __spelling = parser.getToken().getSpelling().str();
  19588. parser.consumeToken(_.Token.bare_identifier);
  19589. result.addAttribute('visibility_', __spelling);
  19590. }
  19591. if (parser.parseOptionalKeyword('thread_local')) {
  19592. result.addAttribute('thread_local_', true);
  19593. }
  19594. const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];
  19595. if (parser.getToken().is(_.Token.bare_identifier) && unnamedAddrKeywords.includes(parser.getTokenSpelling().str())) {
  19596. const __spelling = parser.getToken().getSpelling().str();
  19597. parser.consumeToken(_.Token.bare_identifier);
  19598. result.addAttribute('unnamed_addr', __spelling);
  19599. }
  19600. if (parser.getToken().is(_.Token.at_identifier)) {
  19601. parser.parseSymbolName('sym_name', result.attributes);
  19602. }
  19603. if (parser.getToken().is(_.Token.l_brace)) {
  19604. parser.parseAttributeDict(result.attributes);
  19605. }
  19606. if (parser.parseOptionalColon()) {
  19607. const type = parser.parseType();
  19608. result.addAttribute('alias_type', type);
  19609. }
  19610. if (parser.getToken().is(_.Token.l_brace)) {
  19611. const region = result.addRegion();
  19612. parser.parseRegion(region);
  19613. }
  19614. return true;
  19615. }
  19616. // custom<GEPIndices>($dynamicIndices, $rawConstantIndices)
  19617. parseGEPIndices(parser, op, operands, attrName) {
  19618. // Note: the reference uses 'none' delimiter with TableGen handling brackets,
  19619. // but mlir.js expects '[' already consumed and needs to handle ']' terminator
  19620. const rawConstantIndices = [];
  19621. while (parser.getToken().isNot(_.Token.r_square)) {
  19622. const constIndex = parser.parseOptionalInteger();
  19623. if (constIndex === null) {
  19624. const operand = parser.parseOperand();
  19625. operands.push(operand);
  19626. rawConstantIndices.push(-2147483648);
  19627. } else {
  19628. rawConstantIndices.push(constIndex);
  19629. }
  19630. parser.parseOptionalComma();
  19631. }
  19632. if (rawConstantIndices.length > 0) {
  19633. op.addAttribute(attrName || 'rawConstantIndices', rawConstantIndices);
  19634. }
  19635. }
  19636. parseIndirectBrOpSucessors(parser, op /*, args */) {
  19637. // All operands listed first, then colon, then all types
  19638. parser.parseLSquare();
  19639. const segmentSizes = [];
  19640. if (parser.getToken().isNot(_.Token.r_square)) {
  19641. do {
  19642. const successor = parser.getToken().getSpelling().str();
  19643. parser.consumeToken(_.Token.caret_identifier);
  19644. if (!op.successors) {
  19645. op.successors = [];
  19646. }
  19647. op.successors.push({ name: successor });
  19648. const unresolvedOperands = [];
  19649. const types = [];
  19650. if (parser.parseOptionalLParen()) {
  19651. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.colon)) {
  19652. const operand = parser.parseOperand();
  19653. unresolvedOperands.push(operand);
  19654. if (!parser.parseOptionalComma()) {
  19655. break;
  19656. }
  19657. }
  19658. if (parser.parseOptionalColon()) {
  19659. while (parser.getToken().isNot(_.Token.r_paren)) {
  19660. const type = parser.parseType();
  19661. types.push(type);
  19662. parser.parseOptionalComma();
  19663. }
  19664. }
  19665. parser.parseRParen();
  19666. }
  19667. for (let i = 0; i < unresolvedOperands.length; i++) {
  19668. const type = i < types.length ? types[i] : null;
  19669. parser.resolveOperand(unresolvedOperands[i], type, op.operands);
  19670. }
  19671. segmentSizes.push(unresolvedOperands.length);
  19672. } while (parser.parseOptionalComma());
  19673. }
  19674. parser.parseRSquare();
  19675. if (segmentSizes.length > 0) {
  19676. op.addAttribute('indbr_operand_segments', segmentSizes);
  19677. }
  19678. }
  19679. parseLLVMAllocaOp(parser, result) {
  19680. // llvm.alloca [inalloca] %arraySize x !elemType : (i64) -> !llvm.ptr
  19681. if (parser.parseOptionalKeyword('inalloca')) {
  19682. result.addAttribute('inalloca', true);
  19683. }
  19684. const arraySize = parser.parseOperand();
  19685. parser.parseKeyword('x');
  19686. const elemType = parser.parseType();
  19687. result.addAttribute('elem_type', elemType);
  19688. if (parser.getToken().is(_.Token.l_brace)) {
  19689. parser.parseAttributeDict(result.attributes);
  19690. }
  19691. parser.parseColon();
  19692. const fnType = parser.parseFunctionType();
  19693. if (fnType instanceof _.FunctionType) {
  19694. parser.resolveOperands([arraySize], fnType.inputs, result.operands);
  19695. result.addTypes(fnType.results);
  19696. }
  19697. return true;
  19698. }
  19699. parseLLVMCallOp(parser, result) {
  19700. // llvm.call [cconv] [tailcall] @callee|%ptr (args) [vararg(type)] : func_type
  19701. const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc', 'arm_apcscc', 'arm_aapcscc', 'arm_aapcs_vfpcc', 'aarch64_vector_pcs', 'aarch64_sve_vector_pcs', 'aarch64_sme_preservemost_from_x0', 'aarch64_sme_preservemost_from_x2', 'msp430_intrcc', 'avr_intrcc', 'avr_signalcc', 'ptx_kernelcc', 'ptx_devicecc', 'spir_funccc', 'spir_kernelcc', 'intel_ocl_bicc', 'x86_64_sysvcc', 'win64cc', 'x86_fastcallcc', 'x86_stdcallcc', 'x86_thiscallcc', 'x86_vectorcallcc', 'x86_intrcc', 'amdgpu_vs', 'amdgpu_gs', 'amdgpu_ps', 'amdgpu_cs', 'amdgpu_kernel', 'amdgpu_kernelcc', 'x86_regcallcc', 'amdgpu_hs', 'msp430_builtincc', 'amdgpu_ls', 'amdgpu_es', 'aarch64_vfpcc', 'aarch64_sve_vfpcc', 'wasm_emscripten_invokecc', 'amdgpu_gfx', 'm68k_intrcc'];
  19702. if (parser.getToken().is(_.Token.bare_identifier)) {
  19703. const value = parser.getTokenSpelling().str();
  19704. if (cconvKeywords.includes(value) || /^cc_\d+$/.test(value)) {
  19705. const __spelling = parser.getToken().getSpelling().str();
  19706. parser.consumeToken(_.Token.bare_identifier);
  19707. result.addAttribute('CConv', __spelling);
  19708. }
  19709. }
  19710. const tailcallKeywords = ['none', 'tail', 'musttail', 'notail'];
  19711. if (parser.getToken().is(_.Token.bare_identifier) && tailcallKeywords.includes(parser.getTokenSpelling().str())) {
  19712. const __spelling = parser.getToken().getSpelling().str();
  19713. parser.consumeToken(_.Token.bare_identifier);
  19714. result.addAttribute('TailCallKind', __spelling);
  19715. }
  19716. let isDirect = false;
  19717. let calleePtr = null;
  19718. if (parser.getToken().is(_.Token.at_identifier)) {
  19719. const callee = parser.getToken().getSpelling().str();
  19720. parser.consumeToken(_.Token.at_identifier);
  19721. result.addAttribute('callee', callee);
  19722. isDirect = true;
  19723. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  19724. calleePtr = parser.parseOperand();
  19725. }
  19726. const unresolvedOperands = [];
  19727. parser.parseLParen();
  19728. while (parser.getToken().isNot(_.Token.r_paren)) {
  19729. const arg = parser.parseOperand();
  19730. unresolvedOperands.push(arg);
  19731. parser.parseOptionalComma();
  19732. }
  19733. parser.parseRParen();
  19734. if (parser.parseOptionalKeyword('vararg')) {
  19735. parser.parseLParen();
  19736. const varCalleeType = parser.parseType();
  19737. result.addAttribute('var_callee_type', varCalleeType);
  19738. parser.parseRParen();
  19739. }
  19740. if (parser.parseOptionalLSquare()) {
  19741. if (!parser.parseOptionalRSquare()) {
  19742. const opBundles = [];
  19743. do {
  19744. const tag = parser.getToken().getSpelling().str();
  19745. parser.consumeToken(_.Token.string);
  19746. parser.parseLParen();
  19747. const bundleOperands = [];
  19748. if (parser.getToken().isNot(_.Token.r_paren)) {
  19749. do {
  19750. bundleOperands.push(parser.parseOperand());
  19751. } while (parser.parseOptionalComma());
  19752. parser.parseColon();
  19753. do {
  19754. parser.parseType();
  19755. } while (parser.parseOptionalComma());
  19756. }
  19757. parser.parseRParen();
  19758. opBundles.push({ tag, operands: bundleOperands });
  19759. } while (parser.parseOptionalComma());
  19760. parser.parseRSquare();
  19761. if (opBundles.length > 0) {
  19762. result.addAttribute('op_bundle_tags', opBundles);
  19763. }
  19764. }
  19765. }
  19766. if (parser.getToken().is(_.Token.l_brace)) {
  19767. parser.parseAttributeDict(result.attributes);
  19768. }
  19769. parser.parseColon();
  19770. let calleePtrType = null;
  19771. if (!isDirect) {
  19772. calleePtrType = parser.parseType();
  19773. parser.parseComma();
  19774. }
  19775. const sig = parser.parseFunctionSignature();
  19776. if (calleePtr) {
  19777. parser.resolveOperand(calleePtr, calleePtrType, result.operands);
  19778. }
  19779. parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);
  19780. if (sig.resultTypes.length > 0) {
  19781. result.types = sig.resultTypes.map((t) => t.toString());
  19782. }
  19783. return true;
  19784. }
  19785. parseLLVMCallIntrinsicOp(parser, result) {
  19786. const intrinName = parser.getToken().getSpelling().str();
  19787. parser.consumeToken(_.Token.string);
  19788. result.addAttribute('intrin', intrinName);
  19789. const unresolvedOperands = [];
  19790. parser.parseLParen();
  19791. while (parser.getToken().isNot(_.Token.r_paren)) {
  19792. const arg = parser.parseOperand();
  19793. unresolvedOperands.push(arg);
  19794. parser.parseOptionalComma();
  19795. }
  19796. parser.parseRParen();
  19797. // Parse operation bundles: [] or ["tag"()] or ["tag"(%0, %1 : i32, i32), ...]
  19798. if (parser.parseOptionalLSquare()) {
  19799. if (!parser.parseOptionalRSquare()) {
  19800. const opBundles = [];
  19801. do {
  19802. const tag = parser.getToken().getSpelling().str();
  19803. parser.consumeToken(_.Token.string);
  19804. parser.parseLParen();
  19805. const bundleOperands = [];
  19806. if (parser.getToken().isNot(_.Token.r_paren)) {
  19807. do {
  19808. bundleOperands.push(parser.parseOperand());
  19809. } while (parser.parseOptionalComma());
  19810. parser.parseColon();
  19811. do {
  19812. parser.parseType();
  19813. } while (parser.parseOptionalComma());
  19814. }
  19815. parser.parseRParen();
  19816. opBundles.push({ tag, operands: bundleOperands });
  19817. } while (parser.parseOptionalComma());
  19818. parser.parseRSquare();
  19819. if (opBundles.length > 0) {
  19820. result.addAttribute('op_bundle_tags', opBundles);
  19821. }
  19822. }
  19823. }
  19824. if (parser.getToken().is(_.Token.l_brace)) {
  19825. parser.parseAttributeDict(result.attributes);
  19826. }
  19827. parser.parseColon();
  19828. const sig = parser.parseFunctionSignature();
  19829. parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);
  19830. if (sig.resultTypes.length > 0) {
  19831. result.types = sig.resultTypes.map((t) => t.toString());
  19832. }
  19833. return true;
  19834. }
  19835. parseLLVMCmpOp(parser, result) {
  19836. // llvm.icmp "eq" %lhs, %rhs : i32
  19837. const predicate = parser.getToken().getSpelling().str();
  19838. parser.consumeToken(_.Token.string);
  19839. result.addAttribute('predicate', predicate);
  19840. const lhs = parser.parseOperand();
  19841. parser.parseComma();
  19842. const rhs = parser.parseOperand();
  19843. if (parser.getToken().is(_.Token.l_brace)) {
  19844. parser.parseAttributeDict(result.attributes);
  19845. }
  19846. parser.parseColon();
  19847. const type = parser.parseType();
  19848. parser.resolveOperands([lhs, rhs], [type, type], result.operands);
  19849. // Result type is i1 (or vector/tensor of i1 for vector/tensor operands)
  19850. let resultType = new _.IntegerType('i1');
  19851. if (type instanceof _.VectorType) {
  19852. resultType = new _.VectorType(type.shape, new _.IntegerType('i1'), type.scalableDims);
  19853. } else if (type instanceof _.RankedTensorType) {
  19854. resultType = new _.RankedTensorType(type.shape, new _.IntegerType('i1'), type.encoding);
  19855. }
  19856. result.addTypes([resultType]);
  19857. return true;
  19858. }
  19859. parseLLVMIntrinsicOp(parser, result) {
  19860. const unresolvedOperands = [];
  19861. parser.parseLParen();
  19862. while (parser.getToken().isNot(_.Token.r_paren)) {
  19863. const operand = parser.parseOperand();
  19864. unresolvedOperands.push(operand);
  19865. parser.parseOptionalComma();
  19866. }
  19867. parser.parseRParen();
  19868. if (parser.getToken().is(_.Token.l_brace)) {
  19869. parser.parseAttributeDict(result.attributes);
  19870. }
  19871. const types = parser.parseColonTypeList();
  19872. parser.resolveOperands(unresolvedOperands, types, result.operands);
  19873. if (parser.parseOptionalArrow()) {
  19874. const resultType = parser.parseType();
  19875. result.types = [resultType];
  19876. }
  19877. return true;
  19878. }
  19879. parseLLVMInvokeOp(parser, result) {
  19880. const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc'];
  19881. if (parser.getToken().is(_.Token.bare_identifier)) {
  19882. const value = parser.getTokenSpelling().str();
  19883. if (cconvKeywords.includes(value) || /^cc_\d+$/.test(value)) {
  19884. const __spelling = parser.getToken().getSpelling().str();
  19885. parser.consumeToken(_.Token.bare_identifier);
  19886. result.addAttribute('CConv', __spelling);
  19887. }
  19888. }
  19889. let isDirect = false;
  19890. let funcPtr = null;
  19891. if (parser.getToken().is(_.Token.at_identifier)) {
  19892. isDirect = true;
  19893. const callee = parser.getToken().getSpelling().str();
  19894. parser.consumeToken(_.Token.at_identifier);
  19895. result.addAttribute('callee', callee);
  19896. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  19897. funcPtr = parser.parseOperand();
  19898. }
  19899. const unresolvedOperands = [];
  19900. parser.parseLParen();
  19901. while (parser.getToken().isNot(_.Token.r_paren)) {
  19902. const operand = parser.parseOperand();
  19903. unresolvedOperands.push(operand);
  19904. parser.parseOptionalComma();
  19905. }
  19906. parser.parseRParen();
  19907. parser.parseKeyword('to');
  19908. const normalDest = parser.getToken().getSpelling().str();
  19909. parser.consumeToken(_.Token.caret_identifier);
  19910. result.successors = result.successors || [];
  19911. const normalSucc = { label: normalDest };
  19912. if (parser.parseOptionalLParen()) {
  19913. normalSucc.operands = [];
  19914. while (parser.getToken().isNot(_.Token.r_paren)) {
  19915. const operand = parser.parseOperand();
  19916. normalSucc.operands.push(operand);
  19917. if (parser.parseOptionalColon()) {
  19918. parser.parseType();
  19919. }
  19920. parser.parseOptionalComma();
  19921. }
  19922. parser.parseRParen();
  19923. }
  19924. result.successors.push(normalSucc);
  19925. parser.parseKeyword('unwind');
  19926. const unwindDest = parser.getToken().getSpelling().str();
  19927. parser.consumeToken(_.Token.caret_identifier);
  19928. const unwindSucc = { label: unwindDest };
  19929. if (parser.parseOptionalLParen()) {
  19930. unwindSucc.operands = [];
  19931. while (parser.getToken().isNot(_.Token.r_paren)) {
  19932. const operand = parser.parseOperand();
  19933. unwindSucc.operands.push(operand);
  19934. if (parser.parseOptionalColon()) {
  19935. parser.parseType();
  19936. }
  19937. parser.parseOptionalComma();
  19938. }
  19939. parser.parseRParen();
  19940. }
  19941. result.successors.push(unwindSucc);
  19942. if (parser.parseOptionalKeyword('vararg')) {
  19943. parser.parseLParen();
  19944. const varargType = parser.parseType();
  19945. result.addAttribute('var_callee_type', varargType);
  19946. parser.parseRParen();
  19947. }
  19948. if (parser.parseOptionalLSquare()) {
  19949. if (!parser.parseOptionalRSquare()) {
  19950. const opBundles = [];
  19951. do {
  19952. const tag = parser.getToken().getSpelling().str();
  19953. parser.consumeToken(_.Token.string);
  19954. parser.parseLParen();
  19955. const bundleOperands = [];
  19956. if (parser.getToken().isNot(_.Token.r_paren)) {
  19957. do {
  19958. bundleOperands.push(parser.parseOperand());
  19959. } while (parser.parseOptionalComma());
  19960. parser.parseColon();
  19961. do {
  19962. parser.parseType();
  19963. } while (parser.parseOptionalComma());
  19964. }
  19965. parser.parseRParen();
  19966. opBundles.push({ tag, operands: bundleOperands });
  19967. } while (parser.parseOptionalComma());
  19968. parser.parseRSquare();
  19969. if (opBundles.length > 0) {
  19970. result.addAttribute('op_bundle_tags', opBundles);
  19971. }
  19972. }
  19973. }
  19974. if (parser.getToken().is(_.Token.l_brace)) {
  19975. parser.parseAttributeDict(result.attributes);
  19976. }
  19977. parser.parseColon();
  19978. let calleePtrType = null;
  19979. if (!isDirect) {
  19980. calleePtrType = parser.parseType();
  19981. parser.parseComma();
  19982. }
  19983. const sig = parser.parseFunctionSignature();
  19984. if (funcPtr) {
  19985. parser.resolveOperand(funcPtr, calleePtrType, result.operands);
  19986. }
  19987. parser.resolveOperands(unresolvedOperands, sig.argTypes, result.operands);
  19988. if (sig.resultTypes.length > 0) {
  19989. result.types = sig.resultTypes.map((t) => t.toString());
  19990. }
  19991. return true;
  19992. }
  19993. parseLLVMLandingpadOp(parser, result) {
  19994. if (parser.parseOptionalKeyword('cleanup')) {
  19995. result.addAttribute('cleanup', true);
  19996. }
  19997. while (parser.getToken().is(_.Token.l_paren)) {
  19998. parser.parseLParen();
  19999. parser.consumeToken(_.Token.bare_identifier); // 'catch' or 'filter'
  20000. const operand = parser.parseOperand();
  20001. parser.parseColon();
  20002. const type = parser.parseType();
  20003. parser.resolveOperand(operand, type, result.operands);
  20004. parser.parseRParen();
  20005. }
  20006. parser.parseColon();
  20007. const resultType = parser.parseType();
  20008. result.types = [resultType];
  20009. return true;
  20010. }
  20011. parseLLVMFuncOp(parser, result) {
  20012. const linkageKeywords = ['external', 'available_externally', 'linkonce', 'linkonce_odr', 'weak', 'weak_odr', 'appending', 'internal', 'private', 'extern_weak', 'common'];
  20013. if (parser.getToken().is(_.Token.bare_identifier) && linkageKeywords.includes(parser.getTokenSpelling().str())) {
  20014. const __spelling = parser.getToken().getSpelling().str();
  20015. parser.consumeToken(_.Token.bare_identifier);
  20016. result.addAttribute('linkage', __spelling);
  20017. }
  20018. const visibilityKeywords = ['default', 'hidden', 'protected'];
  20019. if (parser.getToken().is(_.Token.bare_identifier) && visibilityKeywords.includes(parser.getTokenSpelling().str())) {
  20020. const __spelling = parser.getToken().getSpelling().str();
  20021. parser.consumeToken(_.Token.bare_identifier);
  20022. result.addAttribute('visibility_', __spelling);
  20023. }
  20024. const unnamedAddrKeywords = ['unnamed_addr', 'local_unnamed_addr'];
  20025. if (parser.getToken().is(_.Token.bare_identifier) && unnamedAddrKeywords.includes(parser.getTokenSpelling().str())) {
  20026. const __spelling = parser.getToken().getSpelling().str();
  20027. parser.consumeToken(_.Token.bare_identifier);
  20028. result.addAttribute('unnamed_addr', __spelling);
  20029. }
  20030. const cconvKeywords = ['ccc', 'fastcc', 'coldcc', 'cc', 'webkit_jscc', 'anyregcc', 'preserve_mostcc', 'preserve_allcc', 'preserve_nonecc', 'cxx_fast_tlscc', 'tailcc', 'swiftcc', 'swifttailcc', 'cfguard_checkcc', 'ghccc', 'arm_apcscc', 'arm_aapcscc', 'arm_aapcs_vfpcc', 'aarch64_vector_pcs', 'aarch64_sve_vector_pcs', 'aarch64_sme_preservemost_from_x0', 'aarch64_sme_preservemost_from_x2', 'msp430_intrcc', 'avr_intrcc', 'avr_signalcc', 'ptx_kernelcc', 'ptx_devicecc', 'spir_funccc', 'spir_kernelcc', 'intel_ocl_bicc', 'x86_64_sysvcc', 'win64cc', 'x86_fastcallcc', 'x86_stdcallcc', 'x86_thiscallcc', 'x86_vectorcallcc', 'x86_intrcc', 'amdgpu_vs', 'amdgpu_gs', 'amdgpu_ps', 'amdgpu_cs', 'amdgpu_kernel', 'amdgpu_kernelcc', 'x86_regcallcc', 'amdgpu_hs', 'msp430_builtincc', 'amdgpu_ls', 'amdgpu_es', 'aarch64_vfpcc', 'aarch64_sve_vfpcc', 'wasm_emscripten_invokecc', 'amdgpu_gfx', 'm68k_intrcc'];
  20031. if (parser.getToken().is(_.Token.bare_identifier)) {
  20032. const value = parser.getTokenSpelling().str();
  20033. if (cconvKeywords.includes(value) || /^cc_\d+$/.test(value)) {
  20034. const __spelling = parser.getToken().getSpelling().str();
  20035. parser.consumeToken(_.Token.bare_identifier);
  20036. result.addAttribute('CConv', __spelling);
  20037. }
  20038. }
  20039. parser.parseSymbolName('sym_name', result.attributes);
  20040. const argResult = parser.parseFunctionArgumentList(true);
  20041. const params = argResult.arguments.map((a) => a.type);
  20042. const results = [];
  20043. const resultAttrs = [];
  20044. if (parser.parseOptionalArrow()) {
  20045. parser.parseFunctionResultList(results, resultAttrs);
  20046. }
  20047. const returnType = results.length > 0 ? results[0] : null;
  20048. const type = new _.LLVM.LLVMFunctionType(returnType, params, argResult.isVariadic);
  20049. result.addAttribute('function_type', new _.TypeAttrOf(type));
  20050. if (parser.parseOptionalKeyword('vscale_range')) {
  20051. parser.parseLParen();
  20052. const minRange = parser.getToken().getSpelling().str();
  20053. parser.consumeToken();
  20054. parser.parseComma();
  20055. const maxRange = parser.getToken().getSpelling().str();
  20056. parser.consumeToken();
  20057. parser.parseRParen();
  20058. result.addAttribute('vscale_range', `(${minRange}, ${maxRange})`);
  20059. }
  20060. if (parser.parseOptionalKeyword('comdat')) {
  20061. parser.parseLParen();
  20062. const comdat = parser.getToken().getSpelling().str();
  20063. parser.consumeToken(_.Token.at_identifier);
  20064. parser.parseRParen();
  20065. result.addAttribute('comdat', comdat);
  20066. }
  20067. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  20068. if (parser.getToken().is(_.Token.l_brace)) {
  20069. const region = result.addRegion();
  20070. // llvm.func is IsolatedFromAbove
  20071. parser.parseRegion(region, argResult.arguments, /* isIsolatedNameScope */ true);
  20072. }
  20073. return true;
  20074. }
  20075. };
  20076. _.ROCDLDialect = class extends _.LLVM.LLVMDialect {
  20077. constructor(operations) {
  20078. super(operations, 'rocdl');
  20079. }
  20080. parseOperation(parser, result) {
  20081. if (result.op === 'rocdl.raw.buffer.load') {
  20082. return this.parseRawBufferLoadOp(parser, result);
  20083. }
  20084. if (result.op === 'rocdl.raw.buffer.store') {
  20085. return this.parseRawBufferStoreOp(parser, result);
  20086. }
  20087. if (result.op === 'rocdl.raw.buffer.atomic.fadd') {
  20088. return this.parseRawBufferAtomicOp(parser, result);
  20089. }
  20090. if (result.op === 'rocdl.raw.buffer.atomic.fmax') {
  20091. return this.parseRawBufferAtomicOp(parser, result);
  20092. }
  20093. if (result.op === 'rocdl.raw.buffer.atomic.smax') {
  20094. return this.parseRawBufferAtomicOp(parser, result);
  20095. }
  20096. if (result.op === 'rocdl.raw.buffer.atomic.umin') {
  20097. return this.parseRawBufferAtomicOp(parser, result);
  20098. }
  20099. return super.parseOperation(parser, result);
  20100. }
  20101. parseRawBufferLoadOp(parser, result) {
  20102. const unresolvedOperands = [];
  20103. while (parser.getToken().is(_.Token.percent_identifier)) {
  20104. unresolvedOperands.push(parser.parseOperand());
  20105. parser.parseOptionalComma();
  20106. }
  20107. parser.parseColon();
  20108. const resultType = parser.parseType();
  20109. result.addTypes([resultType]);
  20110. for (const operand of unresolvedOperands) {
  20111. parser.resolveOperand(operand, null, result.operands);
  20112. }
  20113. return true;
  20114. }
  20115. parseRawBufferStoreOp(parser, result) {
  20116. const unresolvedOperands = [];
  20117. while (parser.getToken().is(_.Token.percent_identifier)) {
  20118. unresolvedOperands.push(parser.parseOperand());
  20119. parser.parseOptionalComma();
  20120. }
  20121. parser.parseColon();
  20122. parser.parseType();
  20123. for (const operand of unresolvedOperands) {
  20124. parser.resolveOperand(operand, null, result.operands);
  20125. }
  20126. return true;
  20127. }
  20128. parseRawBufferAtomicOp(parser, result) {
  20129. const unresolvedOperands = [];
  20130. while (parser.getToken().is(_.Token.percent_identifier)) {
  20131. unresolvedOperands.push(parser.parseOperand());
  20132. parser.parseOptionalComma();
  20133. }
  20134. parser.parseColon();
  20135. parser.parseType();
  20136. for (const operand of unresolvedOperands) {
  20137. parser.resolveOperand(operand, null, result.operands);
  20138. }
  20139. return true;
  20140. }
  20141. };
  20142. _.XSMMDialect = class extends _.Dialect {
  20143. constructor(operations) {
  20144. super(operations, 'xsmm');
  20145. }
  20146. parseOperation(parser, result) {
  20147. const opInfo = result.name.getRegisteredInfo();
  20148. if (result.op === 'xsmm.unary.invoke') {
  20149. return this.parseUnaryInvokeOp(parser, result);
  20150. }
  20151. if (result.op.startsWith('xsmm.') && result.op.includes('.invoke') && opInfo.metadata.hasCustomAssemblyFormat && !opInfo.metadata.assemblyFormat) {
  20152. return this.parseGemmInvokeOp(parser, result);
  20153. }
  20154. return super.parseOperation(parser, result);
  20155. }
  20156. parseUnaryInvokeOp(parser, result) {
  20157. const unresolvedOperands = [];
  20158. unresolvedOperands.push(parser.parseOperand());
  20159. if (parser.parseOptionalLSquare()) {
  20160. while (!parser.parseOptionalRSquare()) {
  20161. if (parser.getToken().is(_.Token.percent_identifier)) {
  20162. unresolvedOperands.push(parser.parseOperand());
  20163. }
  20164. parser.parseOptionalComma();
  20165. }
  20166. }
  20167. parser.parseEqual();
  20168. unresolvedOperands.push(parser.parseOperand());
  20169. parser.parseLParen();
  20170. unresolvedOperands.push(parser.parseOperand());
  20171. if (parser.parseOptionalLSquare()) {
  20172. while (!parser.parseOptionalRSquare()) {
  20173. if (parser.getToken().is(_.Token.percent_identifier)) {
  20174. unresolvedOperands.push(parser.parseOperand());
  20175. }
  20176. parser.parseOptionalComma();
  20177. }
  20178. }
  20179. parser.parseRParen();
  20180. parser.parseColon();
  20181. parser.parseType();
  20182. for (const operand of unresolvedOperands) {
  20183. parser.resolveOperand(operand, null, result.operands);
  20184. }
  20185. return true;
  20186. }
  20187. parseGemmInvokeOp(parser, result) {
  20188. const unresolvedOperands = [];
  20189. unresolvedOperands.push(parser.parseOperand());
  20190. parser.parseComma();
  20191. unresolvedOperands.push(parser.parseOperand());
  20192. if (parser.parseOptionalLSquare()) {
  20193. while (!parser.parseOptionalRSquare()) {
  20194. if (parser.getToken().is(_.Token.percent_identifier)) {
  20195. unresolvedOperands.push(parser.parseOperand());
  20196. }
  20197. parser.parseOptionalComma();
  20198. }
  20199. }
  20200. parser.parseEqual();
  20201. unresolvedOperands.push(parser.parseOperand());
  20202. if (parser.parseOptionalLSquare()) {
  20203. while (!parser.parseOptionalRSquare()) {
  20204. if (parser.getToken().is(_.Token.percent_identifier)) {
  20205. unresolvedOperands.push(parser.parseOperand());
  20206. }
  20207. parser.parseOptionalComma();
  20208. }
  20209. }
  20210. parser.parseComma();
  20211. unresolvedOperands.push(parser.parseOperand());
  20212. if (parser.parseOptionalLSquare()) {
  20213. while (!parser.parseOptionalRSquare()) {
  20214. if (parser.getToken().is(_.Token.percent_identifier)) {
  20215. unresolvedOperands.push(parser.parseOperand());
  20216. }
  20217. parser.parseOptionalComma();
  20218. }
  20219. }
  20220. while (parser.parseOptionalComma()) {
  20221. if (parser.getToken().is(_.Token.percent_identifier)) {
  20222. unresolvedOperands.push(parser.parseOperand());
  20223. if (parser.parseOptionalLSquare()) {
  20224. while (!parser.parseOptionalRSquare()) {
  20225. if (parser.getToken().is(_.Token.percent_identifier)) {
  20226. unresolvedOperands.push(parser.parseOperand());
  20227. }
  20228. parser.parseOptionalComma();
  20229. }
  20230. }
  20231. } else if (parser.getToken().is(_.Token.bare_identifier)) {
  20232. const keyword = parser.getToken().getSpelling().str();
  20233. parser.consumeToken(_.Token.bare_identifier);
  20234. parser.parseEqual();
  20235. const attrValue = parser.parseAttribute(new _.IntegerType('i64'));
  20236. result.addAttribute(keyword, attrValue);
  20237. } else {
  20238. break;
  20239. }
  20240. }
  20241. parser.parseColon();
  20242. parser.parseType();
  20243. for (const operand of unresolvedOperands) {
  20244. parser.resolveOperand(operand, null, result.operands);
  20245. }
  20246. return true;
  20247. }
  20248. };
  20249. _.StdxDialect = class extends _.Dialect {
  20250. constructor(operations) {
  20251. super(operations, 'stdx');
  20252. }
  20253. parseOperation(parser, result) {
  20254. if (result.op === 'stdx.closure') {
  20255. return this.parseClosureOp(parser, result);
  20256. }
  20257. return super.parseOperation(parser, result);
  20258. }
  20259. parseClosureOp(parser, result) {
  20260. const sig = parser.parseFunctionSignatureWithArguments(false);
  20261. const argTypes = sig.arguments.map((a) => a.type);
  20262. const type = { inputs: argTypes, results: sig.resultTypes };
  20263. result.addAttribute('type', type);
  20264. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  20265. if (parser.getToken().is(_.Token.l_brace)) {
  20266. const region = result.addRegion();
  20267. parser.parseRegion(region, sig.arguments);
  20268. }
  20269. return true;
  20270. }
  20271. };
  20272. _.VMDialect = class extends _.Dialect {
  20273. constructor(operations) {
  20274. super(operations, 'vm');
  20275. this.registerCustomDirective('BranchTableCases', this.parseBranchTableCases.bind(this));
  20276. }
  20277. parseOperation(parser, result) {
  20278. if (result.op === 'vm.func') {
  20279. parser.parseFunctionOp(result, false);
  20280. return true;
  20281. }
  20282. if (result.op === 'vm.cond_fail') {
  20283. // or: vm.cond_fail %status, "message"
  20284. // or: vm.cond_fail %cond, %status
  20285. // or: vm.cond_fail %status
  20286. const unresolvedOperands = [];
  20287. const firstOp = parser.parseOperand();
  20288. unresolvedOperands.push(firstOp);
  20289. if (parser.parseOptionalComma()) {
  20290. // Could be second operand or message
  20291. if (parser.getToken().is(_.Token.percent_identifier)) {
  20292. const secondOp = parser.parseOperand();
  20293. unresolvedOperands.push(secondOp);
  20294. // Optional message
  20295. if (parser.parseOptionalComma()) {
  20296. if (parser.getToken().is(_.Token.string)) {
  20297. const msg = parser.getToken().getSpelling().str();
  20298. parser.consumeToken(_.Token.string);
  20299. result.addAttribute('message', msg);
  20300. }
  20301. }
  20302. } else if (parser.getToken().is(_.Token.string)) {
  20303. const msg = parser.getToken().getSpelling().str();
  20304. parser.consumeToken(_.Token.string);
  20305. result.addAttribute('message', msg);
  20306. }
  20307. }
  20308. for (const unresolved of unresolvedOperands) {
  20309. parser.resolveOperand(unresolved, null, result.operands);
  20310. }
  20311. return true;
  20312. }
  20313. if (result.op === 'vm.import') {
  20314. parser.parseOptionalVisibilityKeyword(result.attributes);
  20315. if (parser.parseOptionalKeyword('optional')) {
  20316. result.addAttribute('is_optional', true);
  20317. }
  20318. parser.parseSymbolName('sym_name', result.attributes);
  20319. if (parser.getToken().is(_.Token.l_paren)) {
  20320. parser.skip('(');
  20321. }
  20322. const inputs = [];
  20323. const results = [];
  20324. const resultAttrs = [];
  20325. if (parser.parseOptionalArrow()) {
  20326. parser.parseFunctionResultList(results, resultAttrs);
  20327. }
  20328. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  20329. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  20330. return true;
  20331. }
  20332. if (result.op === 'vm.export') {
  20333. const functionRef = parser.getToken().getSpelling().str();
  20334. parser.consumeToken(_.Token.at_identifier);
  20335. result.addAttribute('function_ref', functionRef);
  20336. if (parser.parseOptionalKeyword('as')) {
  20337. parser.parseLParen();
  20338. const exportName = parser.getToken().getSpelling().str();
  20339. parser.consumeToken(_.Token.string);
  20340. result.addAttribute('export_name', exportName);
  20341. parser.parseRParen();
  20342. } else {
  20343. result.addAttribute('export_name', functionRef);
  20344. }
  20345. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  20346. return true;
  20347. }
  20348. if (result.op.startsWith('vm.global.') && !result.op.startsWith('vm.global.store.') && !result.op.startsWith('vm.global.load.') && result.op !== 'vm.global.address') {
  20349. result.compatibility = true;
  20350. parser.parseOptionalVisibilityKeyword(result.attributes);
  20351. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'mutable') {
  20352. const mutable = parser.getToken().getSpelling().str();
  20353. parser.consumeToken(_.Token.bare_identifier);
  20354. result.addAttribute('is_mutable', mutable);
  20355. }
  20356. parser.parseSymbolName('sym_name', result.attributes);
  20357. parser.parseOptionalAttrDict(result.attributes);
  20358. if (parser.parseOptionalColon()) {
  20359. const type = parser.parseType();
  20360. result.addAttribute('type', type);
  20361. }
  20362. if (parser.parseOptionalEqual()) {
  20363. const initialValue = parser.parseAttribute();
  20364. result.addAttribute('initial_value', initialValue);
  20365. }
  20366. return true;
  20367. }
  20368. if (result.op === 'vm.initializer') {
  20369. parser.parseOptionalVisibilityKeyword(result.attributes);
  20370. if (parser.getToken().is(_.Token.at_identifier)) {
  20371. parser.parseSymbolName('sym_name', result.attributes);
  20372. }
  20373. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  20374. if (parser.getToken().is(_.Token.l_brace)) {
  20375. const region = result.addRegion();
  20376. parser.parseRegion(region);
  20377. }
  20378. return true;
  20379. }
  20380. if (result.op === 'vm.rodata.inline') {
  20381. result.compatibility = true;
  20382. if (parser.getToken().is(_.Token.string)) {
  20383. const name = parser.getToken().getSpelling().str();
  20384. parser.consumeToken(_.Token.string);
  20385. result.addAttribute('name', name);
  20386. }
  20387. parser.parseOptionalAttrDict(result.attributes);
  20388. result.addTypes(parser.parseOptionalColonTypeList());
  20389. if (parser.parseOptionalEqual()) {
  20390. const value = parser.parseAttribute();
  20391. // Handle type annotation after the value (e.g., dense<...> : vector<21xi8>)
  20392. if (parser.parseOptionalColon()) {
  20393. const valueType = parser.parseType();
  20394. value.type = valueType;
  20395. }
  20396. result.addAttribute('value', value);
  20397. }
  20398. return true;
  20399. }
  20400. if (result.op === 'vm.const.i32.zero') {
  20401. result.compatibility = true;
  20402. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.floatliteral) || parser.getToken().is(_.Token.string)) {
  20403. const value = parser.parseAttribute();
  20404. result.addAttribute('value', value.value === undefined ? value : value.value);
  20405. } else if (parser.getToken().is(_.Token.at_identifier)) {
  20406. const symbol = parser.getToken().getSpelling().str();
  20407. parser.consumeToken(_.Token.at_identifier);
  20408. result.addAttribute('rodata', symbol);
  20409. }
  20410. parser.parseOptionalAttrDict(result.attributes);
  20411. const types = parser.parseOptionalColonTypeList();
  20412. result.addTypes(types.length > 0 ? types : [new _.IntegerType('i32')]);
  20413. return true;
  20414. }
  20415. // Handle vm.switch.ref operation
  20416. if (result.op === 'vm.switch.ref') {
  20417. const unresolvedOperands = [];
  20418. const indexUnresolved = parser.parseOperand();
  20419. unresolvedOperands.push(indexUnresolved);
  20420. parser.parseLSquare();
  20421. while (parser.getToken().isNot(_.Token.r_square)) {
  20422. if (parser.getToken().is(_.Token.percent_identifier)) {
  20423. const value = parser.parseOperand();
  20424. unresolvedOperands.push(value);
  20425. }
  20426. if (!parser.parseOptionalComma()) {
  20427. break;
  20428. }
  20429. }
  20430. parser.parseRSquare();
  20431. parser.parseKeyword('else');
  20432. const defaultValueUnresolved = parser.parseOperand();
  20433. unresolvedOperands.push(defaultValueUnresolved);
  20434. parser.parseOptionalAttrDict(result.attributes);
  20435. let resultType = null;
  20436. if (parser.parseOptionalColon()) {
  20437. resultType = parser.parseType();
  20438. result.addTypes([resultType]);
  20439. }
  20440. for (const unresolved of unresolvedOperands) {
  20441. parser.resolveOperand(unresolved, resultType, result.operands);
  20442. }
  20443. return true;
  20444. }
  20445. // Handle vm.call and vm.call.variadic
  20446. // Variadic has complex syntax like: @callee(op1, op2, [(tuple1), (tuple2)])
  20447. if (result.op === 'vm.call' || result.op === 'vm.call.variadic') {
  20448. result.compatibility = true;
  20449. if (parser.getToken().is(_.Token.at_identifier)) {
  20450. const callee = parser.getToken().getSpelling().str();
  20451. parser.consumeToken(_.Token.at_identifier);
  20452. result.addAttribute('callee', callee);
  20453. }
  20454. if (parser.parseOptionalLParen()) {
  20455. while (parser.getToken().isNot(_.Token.r_paren)) {
  20456. if (parser.getToken().is(_.Token.l_square)) {
  20457. // Skip complex nested structures in variadic calls
  20458. parser.skip('[');
  20459. parser.parseOptionalComma(); // consume trailing comma if present
  20460. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  20461. const operand = parser.parseOperand();
  20462. parser.resolveOperand(operand, null, result.operands);
  20463. parser.parseOptionalComma(); // consume trailing comma if present
  20464. } else {
  20465. // Unexpected token, break to avoid infinite loop
  20466. break;
  20467. }
  20468. }
  20469. parser.parseRParen();
  20470. }
  20471. parser.parseOptionalAttrDict(result.attributes);
  20472. // vm.call.variadic has special syntax with '...' ellipsis
  20473. if (parser.parseOptionalColon()) {
  20474. if (result.op === 'vm.call.variadic') {
  20475. parser.skip('(');
  20476. if (parser.parseOptionalArrow()) {
  20477. const resultTypes = parser.parseFunctionResultTypes();
  20478. result.addTypes(resultTypes);
  20479. }
  20480. } else {
  20481. // Regular vm.call - Reference: uses functional-type(operands, results)
  20482. const type = parser.parseType();
  20483. if (type instanceof _.FunctionType) {
  20484. parser.resolveOperands(result.operands, type.inputs);
  20485. result.addTypes(type.results);
  20486. }
  20487. }
  20488. }
  20489. return true;
  20490. }
  20491. return super.parseOperation(parser, result);
  20492. }
  20493. parseBranchTableCases(parser, op /*, args */) {
  20494. if (parser.parseOptionalKeyword('default')) {
  20495. parser.parseColon();
  20496. const defaultDest = parser.getToken().getSpelling().str();
  20497. parser.consumeToken(_.Token.caret_identifier);
  20498. op.successors = op.successors || [];
  20499. const succ = { dest: defaultDest };
  20500. if (parser.getToken().is(_.Token.l_paren)) {
  20501. parser.parseLParen();
  20502. const operands = [];
  20503. while (parser.getToken().isNot(_.Token.r_paren)) {
  20504. if (parser.getToken().is(_.Token.percent_identifier)) {
  20505. operands.push(parser.parseOperand());
  20506. }
  20507. if (parser.parseOptionalColon()) {
  20508. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.comma)) {
  20509. parser.parseType();
  20510. parser.parseOptionalComma();
  20511. }
  20512. }
  20513. if (!parser.parseOptionalComma()) {
  20514. break;
  20515. }
  20516. }
  20517. parser.parseRParen();
  20518. succ.operands = operands;
  20519. }
  20520. op.successors.push(succ);
  20521. parser.parseOptionalComma();
  20522. }
  20523. const caseValues = [];
  20524. while (parser.getToken().is(_.Token.integer)) {
  20525. const caseValue = parser.parseInteger();
  20526. caseValues.push(caseValue);
  20527. parser.parseColon();
  20528. const caseDest = parser.getToken().getSpelling().str();
  20529. parser.consumeToken(_.Token.caret_identifier);
  20530. const caseSucc = { dest: caseDest };
  20531. if (parser.getToken().is(_.Token.l_paren)) {
  20532. parser.parseLParen();
  20533. const operands = [];
  20534. while (parser.getToken().isNot(_.Token.r_paren)) {
  20535. if (parser.getToken().is(_.Token.percent_identifier)) {
  20536. operands.push(parser.parseOperand());
  20537. }
  20538. if (parser.parseOptionalColon()) {
  20539. while (parser.getToken().isNot(_.Token.r_paren) && parser.getToken().isNot(_.Token.comma)) {
  20540. parser.parseType();
  20541. parser.parseOptionalComma();
  20542. }
  20543. }
  20544. if (!parser.parseOptionalComma()) {
  20545. break;
  20546. }
  20547. }
  20548. parser.parseRParen();
  20549. caseSucc.operands = operands;
  20550. }
  20551. op.successors.push(caseSucc);
  20552. parser.parseOptionalComma();
  20553. }
  20554. if (caseValues.length > 0) {
  20555. op.addAttribute('case_values', caseValues);
  20556. }
  20557. }
  20558. };
  20559. _.MathDialect = class extends _.Dialect {
  20560. constructor(operations) {
  20561. super(operations, 'math');
  20562. this.registerCustomAttribute('Arith_FastMathAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  20563. }
  20564. };
  20565. _.TMTensorDialect = class extends _.Dialect {
  20566. constructor(operations) {
  20567. super(operations, 'tm_tensor');
  20568. }
  20569. };
  20570. _.MLProgramDialect = class extends _.Dialect {
  20571. constructor(operations) {
  20572. super(operations, 'ml_program');
  20573. this.registerCustomDirective('TypedInitialValue', this.parseTypedInitialValue.bind(this));
  20574. this.registerCustomDirective('TokenOrdering', this.parseTokenOrdering.bind(this));
  20575. }
  20576. parseOperation(parser, result) {
  20577. if (result.op === 'ml_program.func' || result.op === 'ml_program.subgraph') {
  20578. parser.parseFunctionOp(result, false);
  20579. return true;
  20580. }
  20581. return super.parseOperation(parser, result);
  20582. }
  20583. parseTokenOrdering(parser, result) {
  20584. if (!parser.parseOptionalKeyword('ordering')) {
  20585. return;
  20586. }
  20587. parser.parseLParen();
  20588. if (parser.parseOptionalLParen()) {
  20589. parser.parseRParen();
  20590. } else {
  20591. while (parser.getToken().is(_.Token.percent_identifier)) {
  20592. const tok = parser.parseOperand();
  20593. parser.resolveOperand(tok, null, result.operands);
  20594. if (!parser.parseOptionalComma()) {
  20595. break;
  20596. }
  20597. }
  20598. }
  20599. parser.parseArrow();
  20600. const produceType = parser.parseType();
  20601. result.addAttribute('produceTokenType', { value: produceType, hidden: true });
  20602. parser.parseRParen();
  20603. }
  20604. parseTypedInitialValue(parser, op, typeAttr, valueAttr) {
  20605. if (parser.parseOptionalLParen()) {
  20606. const attr = parser.parseAttribute();
  20607. if (parser.parseOptionalColon()) {
  20608. attr.type = parser.parseType();
  20609. }
  20610. parser.parseRParen();
  20611. op.addAttribute(valueAttr, attr.value === undefined ? attr : attr.value);
  20612. }
  20613. parser.parseColon();
  20614. const type = parser.parseType();
  20615. op.addAttribute(typeAttr, type);
  20616. }
  20617. };
  20618. _.IREEGPUDialect = class extends _.Dialect {
  20619. constructor(operations) {
  20620. super(operations, 'iree_gpu');
  20621. }
  20622. };
  20623. _.TFDeviceDialect = class extends _.Dialect {
  20624. constructor(operations) {
  20625. super(operations, 'tf_device');
  20626. }
  20627. parseOperation(parser, result) {
  20628. if (result.op === 'tf_device.replicate') {
  20629. return this.parseReplicateOp(parser, result);
  20630. }
  20631. return super.parseOperation(parser, result);
  20632. }
  20633. parseReplicateOp(parser, result) {
  20634. let n = 1;
  20635. if (!parser.parseOptionalLParen()) {
  20636. parser.parseOptionalAttrDict(result.attributes);
  20637. } else if (parser.getToken().is(_.Token.r_paren)) {
  20638. parser.parseRParen();
  20639. parser.parseOptionalAttrDict(result.attributes);
  20640. } else {
  20641. do {
  20642. if (parser.getToken().is(_.Token.l_square)) {
  20643. const unresolvedInputs = [];
  20644. parser.parseLSquare();
  20645. while (!parser.parseOptionalRSquare()) {
  20646. unresolvedInputs.push(parser.parseOperand());
  20647. if (!parser.parseOptionalComma()) {
  20648. parser.parseRSquare();
  20649. break;
  20650. }
  20651. }
  20652. parser.parseKeyword('as');
  20653. parser.parseOperand(); // block arg
  20654. parser.parseColon();
  20655. const type = parser.parseType();
  20656. for (const input of unresolvedInputs) {
  20657. parser.resolveOperand(input, type, result.operands);
  20658. }
  20659. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  20660. const unresolvedValue = parser.parseOperand();
  20661. parser.parseKeyword('as');
  20662. parser.parseOperand(); // block arg
  20663. parser.parseColon();
  20664. const type = parser.parseType();
  20665. parser.resolveOperand(unresolvedValue, type, result.operands);
  20666. } else {
  20667. break;
  20668. }
  20669. } while (parser.parseOptionalComma());
  20670. parser.parseRParen();
  20671. parser.parseOptionalAttrDict(result.attributes);
  20672. }
  20673. n = result.attributes.get('n').value;
  20674. if (parser.getToken().is(_.Token.l_brace)) {
  20675. const region = result.addRegion();
  20676. parser.parseRegion(region);
  20677. if (region.blocks.length > 0) {
  20678. const block = region.blocks[0];
  20679. if (block.operations.length > 0) {
  20680. const terminator = block.operations[block.operations.length - 1];
  20681. if (terminator.operands) {
  20682. for (const operand of terminator.operands) {
  20683. if (operand.type) {
  20684. for (let i = 0; i < n; i++) {
  20685. result.addTypes([operand.type]);
  20686. }
  20687. }
  20688. }
  20689. }
  20690. }
  20691. }
  20692. }
  20693. return true;
  20694. }
  20695. };
  20696. _.TFGDialect = class extends _.Dialect {
  20697. constructor(operations) {
  20698. super(operations, 'tfg');
  20699. }
  20700. getOperation(opName) {
  20701. let op = super.getOperation(opName);
  20702. if (!op) {
  20703. this.registerOperandName(opName, {});
  20704. op = super.getOperation(opName);
  20705. }
  20706. return op;
  20707. }
  20708. parseOperation(parser, result) {
  20709. if (result.op === 'tfg.func') {
  20710. if (parser.parseOptionalKeyword('generic')) {
  20711. result.addAttribute('generic', true);
  20712. }
  20713. parser.parseFunctionOp(result, false);
  20714. return true;
  20715. }
  20716. if (result.op === 'tfg.return') {
  20717. let dataOperands = [];
  20718. if (parser.getToken().is(_.Token.l_paren)) {
  20719. dataOperands = parser.parseOperandList('paren');
  20720. }
  20721. const controlOperands = [];
  20722. const controlRetAttrs = [];
  20723. if (parser.parseOptionalLSquare()) {
  20724. while (parser.getToken().isNot(_.Token.r_square)) {
  20725. if (parser.getToken().is(_.Token.percent_identifier)) {
  20726. const ctlDep = parser.parseOperand();
  20727. controlOperands.push(ctlDep);
  20728. if (parser.getToken().is(_.Token.l_brace)) {
  20729. const attrs = new Map();
  20730. parser.parseAttributeDict(attrs);
  20731. controlRetAttrs.push(Object.fromEntries(attrs));
  20732. } else {
  20733. controlRetAttrs.push({});
  20734. }
  20735. }
  20736. if (!parser.parseOptionalComma()) {
  20737. break;
  20738. }
  20739. }
  20740. parser.parseRSquare();
  20741. }
  20742. if (controlRetAttrs.length > 0) {
  20743. result.addAttribute('control_ret_attrs', controlRetAttrs);
  20744. }
  20745. parser.parseOptionalAttrDict(result.attributes);
  20746. if (parser.parseOptionalColon()) {
  20747. const types = parser.parseTypeListNoParens();
  20748. parser.resolveOperands(dataOperands, types, result.operands);
  20749. } else {
  20750. parser.resolveOperands(dataOperands, dataOperands.map(() => null), result.operands);
  20751. }
  20752. parser.resolveOperands(controlOperands, controlOperands.map(() => null), result.operands);
  20753. return true;
  20754. }
  20755. const opInfo = result.name.getRegisteredInfo();
  20756. if (!opInfo.metadata.assemblyFormat) {
  20757. this.parseTFGOperation(parser, result);
  20758. return true;
  20759. }
  20760. return super.parseOperation(parser, result);
  20761. }
  20762. parseTFGOperation(parser, result) {
  20763. let unresolvedArgs = [];
  20764. if (parser.getToken().is(_.Token.l_paren)) {
  20765. unresolvedArgs = parser.parseOperandList('paren');
  20766. }
  20767. const unresolvedCtls = [];
  20768. if (parser.parseOptionalLSquare()) {
  20769. while (parser.getToken().isNot(_.Token.r_square)) {
  20770. if (parser.getToken().is(_.Token.percent_identifier)) {
  20771. unresolvedCtls.push(parser.parseOperand());
  20772. }
  20773. if (!parser.parseOptionalComma()) {
  20774. break;
  20775. }
  20776. }
  20777. parser.parseRSquare();
  20778. }
  20779. if (parser.parseOptionalKeyword('device')) {
  20780. parser.parseLParen();
  20781. const device = parser.getToken().getSpelling().str();
  20782. parser.consumeToken(_.Token.string);
  20783. parser.parseRParen();
  20784. result.addAttribute('device', device);
  20785. }
  20786. if (parser.parseOptionalKeyword('name')) {
  20787. parser.parseLParen();
  20788. const name = parser.getToken().getSpelling().str();
  20789. parser.consumeToken(_.Token.string);
  20790. parser.parseRParen();
  20791. result.addAttribute('_mlir_name', name);
  20792. }
  20793. if (parser.getToken().is(_.Token.l_brace)) {
  20794. parser.parseAttributeDict(result.attributes);
  20795. }
  20796. if (parser.parseOptionalColon()) {
  20797. const type = parser.parseType();
  20798. if (type instanceof _.FunctionType) {
  20799. parser.resolveOperands(unresolvedArgs, type.inputs, result.operands);
  20800. parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);
  20801. result.addTypes(type.results);
  20802. } else {
  20803. const types = [type];
  20804. while (parser.parseOptionalComma()) {
  20805. types.push(parser.parseType());
  20806. }
  20807. parser.resolveOperands(unresolvedArgs, types, result.operands);
  20808. parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);
  20809. }
  20810. } else {
  20811. parser.resolveOperands(unresolvedArgs, unresolvedArgs.map(() => null), result.operands);
  20812. parser.resolveOperands(unresolvedCtls, unresolvedCtls.map(() => new _.Type('!tfg.control')), result.operands);
  20813. }
  20814. result.addTypes([new _.Type('!tfg.control')]);
  20815. }
  20816. };
  20817. _.TFExecutorDialect = class extends _.Dialect {
  20818. constructor(operations) {
  20819. super(operations, 'tf_executor');
  20820. }
  20821. parseType(parser, dialect) {
  20822. const typeName = parser.parseOptionalKeyword();
  20823. if (!typeName) {
  20824. return null;
  20825. }
  20826. const type = `!${dialect}.${typeName}`;
  20827. if (typeName === 'control' || typeName === 'token') {
  20828. return new _.Type(type);
  20829. }
  20830. return null;
  20831. }
  20832. parseOperation(parser, result) {
  20833. if (result.op === 'tf_executor.graph') {
  20834. return this.parseGraphOp(parser, result);
  20835. }
  20836. if (result.op === 'tf_executor.island') {
  20837. return this.parseIslandOp(parser, result);
  20838. }
  20839. if (result.op === 'tf_executor.Enter') {
  20840. return this.parseEnterOp(parser, result);
  20841. }
  20842. if (result.op === 'tf_executor._SwitchN') {
  20843. const unresolvedData = parser.parseOperand();
  20844. parser.parseComma();
  20845. const unresolvedIndex = parser.parseOperand();
  20846. parser.parseKeyword('of');
  20847. const numOuts = parseInt(parser.getToken().getSpelling().str(), 10);
  20848. parser.consumeToken(_.Token.integer);
  20849. result.addAttribute('num_outs', numOuts);
  20850. let unresolvedControlInputs = [];
  20851. if (parser.getToken().is(_.Token.l_paren)) {
  20852. unresolvedControlInputs = parser.parseOperandList('paren');
  20853. }
  20854. parser.parseColon();
  20855. const type = parser.parseType();
  20856. parser.resolveOperand(unresolvedData, type, result.operands);
  20857. parser.resolveOperand(unresolvedIndex, new _.RankedTensorType([], new _.IntegerType('i32'), null), result.operands);
  20858. parser.resolveOperands(unresolvedControlInputs, unresolvedControlInputs.map(() => new _.Type('!tf_executor.control')), result.operands);
  20859. for (let i = 0; i < numOuts; i++) {
  20860. result.addTypes([type]);
  20861. }
  20862. result.addTypes([new _.Type('!tf_executor.control')]);
  20863. parser.parseOptionalAttrDict(result.attributes);
  20864. return true;
  20865. }
  20866. if (result.op === 'tf_executor.Switch' || result.op === 'tf_executor.Merge' ||
  20867. result.op === 'tf_executor.LoopCond' || result.op === 'tf_executor.Exit') {
  20868. // These ops have hasCustomAssemblyFormat: true but no assemblyFormat in metadata
  20869. const unresolvedOperands = parser.parseOperandList();
  20870. if (parser.parseOptionalColon()) {
  20871. const type = parser.parseType();
  20872. if (type instanceof _.FunctionType) {
  20873. parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);
  20874. result.addTypes(type.results);
  20875. } else {
  20876. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => type), result.operands);
  20877. result.addTypes([type]);
  20878. if (result.op === 'tf_executor.Switch') {
  20879. result.addTypes([type]);
  20880. }
  20881. if (result.op === 'tf_executor.Merge') {
  20882. result.addTypes([new _.RankedTensorType([], new _.IntegerType('i32'), null)]);
  20883. }
  20884. result.addTypes([new _.Type('!tf_executor.control')]);
  20885. }
  20886. } else {
  20887. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  20888. }
  20889. parser.parseOptionalAttrDict(result.attributes);
  20890. return true;
  20891. }
  20892. return super.parseOperation(parser, result);
  20893. }
  20894. parseEnterOp(parser, result) {
  20895. const unresolvedOperands = [];
  20896. while (parser.getToken().is(_.Token.percent_identifier)) {
  20897. unresolvedOperands.push(parser.parseOperand());
  20898. if (!parser.parseOptionalComma()) {
  20899. break;
  20900. }
  20901. }
  20902. parser.parseKeyword('frame');
  20903. const frameName = parser.getToken().getSpelling().str();
  20904. parser.consumeToken(_.Token.string);
  20905. result.addAttribute('frame_name', frameName);
  20906. if (parser.parseOptionalKeyword('parallel_iterations')) {
  20907. const parallelIterations = parser.getToken().getSpelling().str();
  20908. parser.consumeToken(_.Token.integer);
  20909. result.addAttribute('parallel_iterations', parseInt(parallelIterations, 10));
  20910. } else {
  20911. result.addAttribute('parallel_iterations', 10);
  20912. }
  20913. const isConstant = parser.parseOptionalKeyword('constant');
  20914. result.addAttribute('is_constant', isConstant);
  20915. parser.parseColon();
  20916. const type = parser.parseType();
  20917. if (type instanceof _.FunctionType) {
  20918. parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);
  20919. result.addTypes(type.results);
  20920. } else {
  20921. const resolveTypes = unresolvedOperands.map((v, i) => i === 0 ? type : new _.Type('!tf_executor.control'));
  20922. parser.resolveOperands(unresolvedOperands, resolveTypes, result.operands);
  20923. result.addTypes([type]);
  20924. result.addTypes([new _.Type('!tf_executor.control')]);
  20925. }
  20926. parser.parseOptionalAttrDict(result.attributes);
  20927. return true;
  20928. }
  20929. parseGraphOp(parser, result) {
  20930. if (parser.getToken().is(_.Token.l_brace)) {
  20931. const region = result.addRegion();
  20932. parser.parseRegion(region);
  20933. if (region.blocks && region.blocks.length > 0) {
  20934. const [block] = region.blocks;
  20935. if (block.operations && block.operations.length > 0) {
  20936. const lastOp = block.operations[block.operations.length - 1];
  20937. if (lastOp.name.getStringRef() === 'tf_executor.fetch' && lastOp.operands) {
  20938. for (const operand of lastOp.operands) {
  20939. const typeStr = operand.type ? operand.type.toString() : '';
  20940. if (operand.type && typeStr !== '!tf_executor.control') {
  20941. result.addTypes([operand.type]);
  20942. }
  20943. }
  20944. }
  20945. }
  20946. }
  20947. }
  20948. parser.parseOptionalAttrDict(result.attributes);
  20949. return true;
  20950. }
  20951. parseIslandOp(parser, result) {
  20952. // or: tf_executor.island {...}
  20953. // or: tf_executor.island(%control_inputs) {...}
  20954. if (parser.getToken().is(_.Token.l_paren)) {
  20955. const unresolvedOperands = parser.parseOperandList('paren');
  20956. for (const operand of unresolvedOperands) {
  20957. parser.resolveOperand(operand, null, result.operands);
  20958. }
  20959. }
  20960. const region = result.addRegion();
  20961. if (parser.parseOptionalKeyword('wraps')) {
  20962. const wrappedOp = parser.parseGenericOperation();
  20963. result.addAttribute('wrappedOp', wrappedOp);
  20964. for (const opResult of wrappedOp.results) {
  20965. result.addTypes([opResult.type]);
  20966. }
  20967. } else if (parser.getToken().is(_.Token.l_brace)) {
  20968. parser.parseRegion(region);
  20969. if (region.blocks.length > 0) {
  20970. const block = region.blocks[region.blocks.length - 1];
  20971. if (block.operations.length > 0) {
  20972. const terminator = block.operations[block.operations.length - 1];
  20973. if (terminator.name.getStringRef() === 'tf_executor.yield') {
  20974. for (const operand of terminator.operands) {
  20975. result.addTypes([operand.type]);
  20976. }
  20977. }
  20978. }
  20979. }
  20980. }
  20981. result.addTypes([new _.Type('!tf_executor.control')]);
  20982. parser.parseOptionalAttrDict(result.attributes);
  20983. return true;
  20984. }
  20985. };
  20986. _.TFFrameworkDialect = class extends _.Dialect {
  20987. constructor(operations) {
  20988. super(operations, 'tf_framework');
  20989. }
  20990. };
  20991. _.TFRDialect = class extends _.Dialect {
  20992. constructor(operations) {
  20993. super(operations, 'tfr');
  20994. }
  20995. parseOperation(parser, result) {
  20996. if (result.op === 'tfr.func') {
  20997. parser.parseFunctionOp(result, false);
  20998. return true;
  20999. }
  21000. return super.parseOperation(parser, result);
  21001. }
  21002. };
  21003. _.CoreRTDialect = class extends _.Dialect {
  21004. constructor(operations) {
  21005. super(operations, 'corert');
  21006. }
  21007. parseOperation(parser, result) {
  21008. if (result.op === 'corert.executeop' || result.op === 'corert.executeop.seq') {
  21009. const isSeq = result.op === 'corert.executeop.seq';
  21010. const opHandlerOperands = parser.parseOperandList('paren');
  21011. for (const operand of opHandlerOperands) {
  21012. parser.resolveOperand(operand, null, result.operands);
  21013. }
  21014. const opNameAttr = parser.getToken().getSpelling().str();
  21015. parser.consumeToken(_.Token.string);
  21016. result.addAttribute('op_name', opNameAttr);
  21017. const operandOperands = parser.parseOperandList('paren');
  21018. for (const operand of operandOperands) {
  21019. parser.resolveOperand(operand, null, result.operands);
  21020. }
  21021. if (parser.getToken().is(_.Token.l_brace)) {
  21022. parser.parseAttributeDict(result.attributes);
  21023. }
  21024. if (parser.getToken().is(_.Token.l_brace)) {
  21025. const funcAttrs = new Map();
  21026. parser.parseAttributeDict(funcAttrs);
  21027. result.addAttribute('op_func_attrs', Object.fromEntries(funcAttrs));
  21028. }
  21029. if (parser.parseOptionalColon()) {
  21030. const resultCount = parseInt(parser.getToken().getSpelling().str(), 10);
  21031. parser.consumeToken(_.Token.integer);
  21032. if (isSeq) {
  21033. result.addTypes([new _.Type('!tfrt.chain')]);
  21034. }
  21035. const tensorHandleType = new _.Type('!corert.tensorhandle');
  21036. for (let i = 0; i < resultCount; i++) {
  21037. result.addTypes([tensorHandleType]);
  21038. }
  21039. } else if (isSeq) {
  21040. result.addTypes([new _.Type('!tfrt.chain')]);
  21041. }
  21042. return true;
  21043. }
  21044. return super.parseOperation(parser, result);
  21045. }
  21046. };
  21047. _.TFRTDialect = class extends _.Dialect {
  21048. constructor(operations) {
  21049. super(operations, 'tfrt');
  21050. }
  21051. parseType(parser, dialect) {
  21052. const typeName = parser.parseOptionalKeyword();
  21053. if (!typeName) {
  21054. return null;
  21055. }
  21056. let type = `!${dialect}.${typeName}`;
  21057. const simpleTypes = ['chain', 'string', 'dist_context', 'device', 'tensor_type'];
  21058. if (simpleTypes.includes(typeName)) {
  21059. return new _.Type(type);
  21060. }
  21061. if (typeName === 'tensor') {
  21062. if (parser.getToken().is(_.Token.less)) {
  21063. const content = parser.skip('<');
  21064. type += content;
  21065. }
  21066. return new _.Type(type);
  21067. }
  21068. // Fallback for unknown tfrt types
  21069. if (parser.getToken().is(_.Token.less)) {
  21070. type += parser.skip('<');
  21071. }
  21072. return new _.Type(type);
  21073. }
  21074. parseOperation(parser, result) {
  21075. const opInfo = result.name.getRegisteredInfo();
  21076. if (!opInfo) {
  21077. return false;
  21078. }
  21079. if (opInfo.metadata.assemblyFormat === 'operands attr-dict') {
  21080. const unresolvedOperands = [];
  21081. while (parser.getToken().is(_.Token.percent_identifier)) {
  21082. unresolvedOperands.push(parser.parseOperand());
  21083. if (!parser.parseOptionalComma()) {
  21084. break;
  21085. }
  21086. }
  21087. if (parser.getToken().is(_.Token.l_brace)) {
  21088. parser.parseAttributeDict(result.attributes);
  21089. }
  21090. for (const unresolved of unresolvedOperands) {
  21091. parser.resolveOperand(unresolved, null, result.operands);
  21092. }
  21093. this.inferResultTypes(result, new Map());
  21094. return true;
  21095. }
  21096. if (result.op === 'tfrt.call') {
  21097. parser.parseSymbolName('callee', result.attributes);
  21098. const unresolvedOperands = parser.parseOperandList('paren');
  21099. parser.parseOptionalAttrDict(result.attributes);
  21100. if (parser.parseOptionalColon()) {
  21101. const type = parser.parseFunctionType();
  21102. if (type) {
  21103. if (type.inputs) {
  21104. parser.resolveOperands(unresolvedOperands, type.inputs, result.operands);
  21105. }
  21106. if (type.results) {
  21107. type.results.forEach((resultType) => {
  21108. result.addTypes([resultType]);
  21109. });
  21110. }
  21111. }
  21112. } else {
  21113. for (const operand of unresolvedOperands) {
  21114. parser.resolveOperand(operand, null, result.operands);
  21115. }
  21116. }
  21117. return true;
  21118. }
  21119. if (result.op === 'tfrt.return') {
  21120. if (parser.getToken().isNot(_.Token.kw_loc) && parser.getToken().isNot(_.Token.eof)) {
  21121. const unresolvedOperands = parser.parseOperandList();
  21122. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  21123. }
  21124. return true;
  21125. }
  21126. if (result.op === 'tfrt.repeat.i32') {
  21127. const unresolvedOperands = parser.parseOperandList();
  21128. if (parser.parseOptionalKeyword('attributes')) {
  21129. parser.parseOptionalAttrDict(result.attributes);
  21130. }
  21131. const types = parser.parseOptionalColonTypeList();
  21132. result.addTypes(types);
  21133. if (unresolvedOperands.length > 0) {
  21134. const i32Type = new _.IntegerType('i32');
  21135. parser.resolveOperand(unresolvedOperands[0], i32Type, result.operands);
  21136. const loopOperands = unresolvedOperands.slice(1);
  21137. parser.resolveOperands(loopOperands, types, result.operands);
  21138. }
  21139. if (parser.getToken().is(_.Token.l_brace)) {
  21140. const region = result.addRegion();
  21141. parser.parseRegion(region);
  21142. }
  21143. return true;
  21144. }
  21145. if (result.op === 'tfrt.if') {
  21146. const unresolvedOperands = parser.parseOperandList();
  21147. if (parser.parseOptionalKeyword('attributes')) {
  21148. parser.parseOptionalAttrDict(result.attributes);
  21149. }
  21150. if (parser.parseOptionalColon()) {
  21151. const funcType = parser.parseFunctionType();
  21152. if (funcType) {
  21153. if (funcType.inputs) {
  21154. parser.resolveOperands(unresolvedOperands, funcType.inputs, result.operands);
  21155. }
  21156. if (funcType.results) {
  21157. for (const resultType of funcType.results) {
  21158. result.addTypes([resultType]);
  21159. }
  21160. }
  21161. }
  21162. } else {
  21163. for (const operand of unresolvedOperands) {
  21164. parser.resolveOperand(operand, null, result.operands);
  21165. }
  21166. }
  21167. if (parser.getToken().is(_.Token.l_brace)) {
  21168. const thenRegion = {};
  21169. parser.parseRegion(thenRegion);
  21170. result.regions.push(thenRegion);
  21171. }
  21172. if (parser.parseOptionalKeyword('else')) {
  21173. if (parser.getToken().is(_.Token.l_brace)) {
  21174. const elseRegion = {};
  21175. parser.parseRegion(elseRegion);
  21176. result.regions.push(elseRegion);
  21177. }
  21178. }
  21179. return true;
  21180. }
  21181. if (result.op === 'tfrt.parallel_for.i32') {
  21182. const startUnresolved = parser.parseOperand();
  21183. parser.parseKeyword('to');
  21184. const endUnresolved = parser.parseOperand();
  21185. parser.parseKeyword('fixed');
  21186. const blockSizeUnresolved = parser.parseOperand();
  21187. let additionalArgs = [];
  21188. if (parser.parseOptionalComma()) {
  21189. additionalArgs = parser.parseOperandList();
  21190. }
  21191. const types = parser.parseOptionalColonTypeList();
  21192. const i32Type = new _.IntegerType('i32');
  21193. parser.resolveOperand(startUnresolved, i32Type, result.operands);
  21194. parser.resolveOperand(endUnresolved, i32Type, result.operands);
  21195. parser.resolveOperand(blockSizeUnresolved, i32Type, result.operands);
  21196. parser.resolveOperands(additionalArgs, types, result.operands);
  21197. result.addTypes([new _.Type('!tfrt.chain')]);
  21198. if (parser.getToken().is(_.Token.l_brace)) {
  21199. const region = result.addRegion();
  21200. parser.parseRegion(region);
  21201. }
  21202. return true;
  21203. }
  21204. if (result.op === 'tfrt.parallel_call.i32') {
  21205. const startUnresolved = parser.parseOperand();
  21206. parser.parseKeyword('to');
  21207. const endUnresolved = parser.parseOperand();
  21208. parser.parseKeyword('fixed');
  21209. const blockSizeUnresolved = parser.parseOperand();
  21210. const callee = parser.getToken().getSpelling().str();
  21211. parser.consumeToken(_.Token.at_identifier);
  21212. result.addAttribute('callee', callee);
  21213. const additionalArgs = parser.parseOperandList('paren');
  21214. const types = parser.parseOptionalColonTypeList();
  21215. const i32Type = new _.IntegerType('i32');
  21216. parser.resolveOperand(startUnresolved, i32Type, result.operands);
  21217. parser.resolveOperand(endUnresolved, i32Type, result.operands);
  21218. parser.resolveOperand(blockSizeUnresolved, i32Type, result.operands);
  21219. parser.resolveOperands(additionalArgs, types, result.operands);
  21220. result.addTypes([new _.Type('!tfrt.chain')]);
  21221. return true;
  21222. }
  21223. if (result.op === 'tfrt.while') {
  21224. const condUnresolved = parser.parseOperand();
  21225. const bodyFn = parser.getToken().getSpelling().str();
  21226. parser.consumeToken(_.Token.at_identifier);
  21227. result.addAttribute('body_fn', bodyFn);
  21228. parser.parseLParen();
  21229. const argsUnresolved = [];
  21230. while (parser.getToken().isNot(_.Token.r_paren)) {
  21231. const arg = parser.parseOperand();
  21232. argsUnresolved.push(arg);
  21233. if (!parser.parseOptionalComma()) {
  21234. break;
  21235. }
  21236. }
  21237. parser.parseRParen();
  21238. if (parser.getToken().is(_.Token.l_brace)) {
  21239. parser.parseAttributeDict(result.attributes);
  21240. }
  21241. if (parser.parseOptionalKeyword('parallel_iterations')) {
  21242. parser.parseLParen();
  21243. const parallelIterations = parser.getToken().getSpelling().str();
  21244. parser.consumeToken(_.Token.integer);
  21245. result.addAttribute('parallel_iterations', parseInt(parallelIterations, 10));
  21246. parser.parseRParen();
  21247. }
  21248. parser.parseColon();
  21249. const inputTypes = parser.parseTypeListParens();
  21250. parser.parseArrow();
  21251. const resultTypes = parser.parseTypeListParens();
  21252. parser.resolveOperand(condUnresolved, new _.IntegerType('i1'), result.operands);
  21253. parser.resolveOperands(argsUnresolved, inputTypes, result.operands);
  21254. for (const resultType of resultTypes) {
  21255. result.addTypes([resultType]);
  21256. }
  21257. return true;
  21258. }
  21259. return super.parseOperation(parser, result);
  21260. }
  21261. };
  21262. _.TFRTFallbackAsyncDialect = class extends _.Dialect {
  21263. constructor(operations) {
  21264. super(operations, 'tfrt_fallback_async');
  21265. }
  21266. parseOperation(parser, result) {
  21267. const opInfo = result.name.getRegisteredInfo();
  21268. if (!opInfo) {
  21269. return false;
  21270. }
  21271. if (result.op === 'tfrt_fallback_async.batch_function') {
  21272. parser.parseKeyword('device');
  21273. parser.parseLParen();
  21274. const device = parser.getToken().getSpelling().str();
  21275. parser.consumeToken(_.Token.string);
  21276. parser.parseRParen();
  21277. result.addAttribute('device', device);
  21278. const funcName = parser.getToken().getSpelling().str();
  21279. parser.consumeToken(_.Token.at_identifier);
  21280. result.addAttribute('f', funcName);
  21281. const unresolvedOperands = parser.parseOperandList('paren');
  21282. for (const operand of unresolvedOperands) {
  21283. parser.resolveOperand(operand, null, result.operands);
  21284. }
  21285. if (parser.getToken().is(_.Token.l_brace)) {
  21286. parser.parseAttributeDict(result.attributes);
  21287. if (parser.getToken().is(_.Token.l_brace)) {
  21288. parser.parseAttributeDict(result.attributes);
  21289. }
  21290. }
  21291. if (parser.parseOptionalColon()) {
  21292. const resultCount = parseInt(parser.getToken().getSpelling().str(), 10);
  21293. parser.consumeToken();
  21294. for (let i = 0; i < resultCount; i++) {
  21295. result.addTypes([new _.Type('!tfrt_fallback.tf_tensor')]);
  21296. }
  21297. }
  21298. return true;
  21299. }
  21300. if (result.op === 'tfrt_fallback_async.createop' || result.op.startsWith('tfrt_fallback_async.executeop')) {
  21301. const isCreateOp = result.op === 'tfrt_fallback_async.createop';
  21302. const hasChain = isCreateOp || result.op.includes('.seq');
  21303. const hasAllocator = result.op.includes('.allocator');
  21304. if ((hasChain || hasAllocator) && parser.getToken().is(_.Token.l_paren)) {
  21305. const chainOperands = parser.parseOperandList('paren');
  21306. for (const operand of chainOperands) {
  21307. parser.resolveOperand(operand, null, result.operands);
  21308. }
  21309. }
  21310. while (parser.getToken().isNot(_.Token.colon) && parser.getToken().isNot(_.Token.l_brace)) {
  21311. if (parser.getToken().is(_.Token.bare_identifier)) {
  21312. const key = parser.getToken().getSpelling().str();
  21313. parser.consumeToken(_.Token.bare_identifier);
  21314. if (parser.parseOptionalLParen()) {
  21315. const value = parser.getToken().getSpelling().str();
  21316. parser.consumeToken();
  21317. parser.parseRParen();
  21318. result.addAttribute(key, value);
  21319. }
  21320. } else if (parser.getToken().is(_.Token.string)) {
  21321. const opNameAttr = parser.getToken().getSpelling().str();
  21322. parser.consumeToken(_.Token.string);
  21323. result.addAttribute('op_name', opNameAttr);
  21324. if (parser.getToken().is(_.Token.l_paren)) {
  21325. const unresolvedOperands = parser.parseOperandList('paren');
  21326. for (const operand of unresolvedOperands) {
  21327. parser.resolveOperand(operand, null, result.operands);
  21328. }
  21329. }
  21330. break;
  21331. } else {
  21332. break;
  21333. }
  21334. }
  21335. if (parser.getToken().is(_.Token.l_brace)) {
  21336. parser.parseAttributeDict(result.attributes);
  21337. if (parser.getToken().is(_.Token.l_brace)) {
  21338. parser.parseAttributeDict(result.attributes);
  21339. }
  21340. }
  21341. if (isCreateOp) {
  21342. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'num_args') {
  21343. parser.consumeToken(_.Token.bare_identifier);
  21344. parser.parseLParen();
  21345. const numArgs = parser.getToken().getSpelling().str();
  21346. parser.consumeToken();
  21347. parser.parseRParen();
  21348. result.addAttribute('num_args', parseInt(numArgs, 10));
  21349. }
  21350. // createop always returns !tfrt.chain
  21351. result.addTypes([new _.Type('!tfrt.chain')]);
  21352. } else if (parser.parseOptionalColon()) {
  21353. const resultCount = parseInt(parser.getToken().getSpelling().str(), 10);
  21354. parser.consumeToken();
  21355. result.addAttribute('result_count', resultCount);
  21356. if (hasChain) {
  21357. result.addTypes([new _.Type('!tfrt.chain')]);
  21358. }
  21359. for (let i = 0; i < resultCount; i++) {
  21360. result.addTypes([new _.Type('!tfrt_fallback.tf_tensor')]);
  21361. }
  21362. } else if (hasChain) {
  21363. result.addTypes([new _.Type('!tfrt.chain')]);
  21364. }
  21365. return true;
  21366. }
  21367. return super.parseOperation(parser, result);
  21368. }
  21369. };
  21370. _.TileDialect = class extends _.Dialect {
  21371. constructor(operations) {
  21372. super(operations, 'tile');
  21373. }
  21374. parseOperation(parser, result) {
  21375. // tile.contract has format: tile.contract agg, combo, operands... attributes : types -> result
  21376. // Example: %1 = tile.contract add, mul, %0, %arg0, %arg1 {sink = #map0, srcs = [#map1, #map2]} : tensor<f32>, tensor<1x256xf32>, tensor<256x512xf32> -> tensor<1x512xf32>
  21377. if (result.op === 'tile.contract') {
  21378. if (parser.getToken().is(_.Token.bare_identifier)) {
  21379. const agg = parser.getToken().getSpelling().str();
  21380. parser.consumeToken(_.Token.bare_identifier);
  21381. result.addAttribute('agg', agg);
  21382. }
  21383. parser.parseOptionalComma();
  21384. if (parser.getToken().is(_.Token.bare_identifier)) {
  21385. const combo = parser.getToken().getSpelling().str();
  21386. parser.consumeToken(_.Token.bare_identifier);
  21387. result.addAttribute('combo', combo);
  21388. }
  21389. parser.parseOptionalComma();
  21390. const unresolvedOperands = parser.parseOperandList();
  21391. if (parser.getToken().is(_.Token.l_brace)) {
  21392. parser.parseAttributeDict(result.attributes);
  21393. }
  21394. parser.resolveOperands(unresolvedOperands, parser.parseOptionalColonTypeList(), result.operands);
  21395. if (parser.parseOptionalArrow()) {
  21396. const resultTypes = parser.parseFunctionResultTypes();
  21397. result.addTypes(resultTypes);
  21398. }
  21399. return true;
  21400. }
  21401. return super.parseOperation(parser, result);
  21402. }
  21403. };
  21404. _.PXADialect = class extends _.Dialect {
  21405. constructor(operations) {
  21406. super(operations, 'pxa');
  21407. }
  21408. parseOperation(parser, result) {
  21409. if (result.op === 'pxa.reduce' || result.op === 'pxa.vector_reduce') {
  21410. const agg = parser.getToken().getSpelling().str();
  21411. parser.consumeToken(_.Token.bare_identifier);
  21412. result.addAttribute('agg', agg);
  21413. const unresolvedVal = parser.parseOperand();
  21414. parser.parseOptionalComma();
  21415. const unresolvedMemref = parser.parseOperand();
  21416. parser.skip('[');
  21417. parser.parseOptionalAttrDict(result.attributes);
  21418. let memrefType = null;
  21419. let valType = null;
  21420. if (parser.parseOptionalColon()) {
  21421. memrefType = parser.parseType();
  21422. result.addTypes([memrefType]);
  21423. if (result.op === 'pxa.vector_reduce' && parser.parseOptionalComma()) {
  21424. valType = parser.parseType();
  21425. }
  21426. }
  21427. parser.resolveOperand(unresolvedVal, valType, result.operands);
  21428. parser.resolveOperand(unresolvedMemref, memrefType, result.operands);
  21429. return true;
  21430. }
  21431. if (result.op === 'pxa.load' || result.op === 'pxa.vector_load') {
  21432. const unresolvedMemref = parser.parseOperand();
  21433. parser.skip('[');
  21434. parser.parseOptionalAttrDict(result.attributes);
  21435. let memrefType = null;
  21436. if (parser.parseOptionalColon()) {
  21437. memrefType = parser.parseType();
  21438. if (result.op === 'pxa.vector_load' && parser.parseOptionalComma()) {
  21439. const vectorType = parser.parseType();
  21440. result.addTypes([vectorType]);
  21441. } else if (result.op === 'pxa.load' && memrefType) {
  21442. // Result type is element type of memref
  21443. const elementType = memrefType.elementType || memrefType;
  21444. result.addTypes([elementType]);
  21445. }
  21446. }
  21447. parser.resolveOperand(unresolvedMemref, memrefType, result.operands);
  21448. return true;
  21449. }
  21450. if (result.op === 'pxa.generic') {
  21451. const unresolvedOperands = [];
  21452. if (parser.parseOptionalLParen()) {
  21453. while (parser.getToken().isNot(_.Token.r_paren)) {
  21454. const operand = parser.parseOperand();
  21455. unresolvedOperands.push(operand);
  21456. if (parser.getToken().is(_.Token.l_square)) {
  21457. parser.skip('[');
  21458. }
  21459. if (parser.parseOptionalColon()) {
  21460. parser.consumeToken(_.Token.hash_identifier); // Skip affine map reference
  21461. }
  21462. if (!parser.parseOptionalComma()) {
  21463. break;
  21464. }
  21465. }
  21466. parser.parseRParen();
  21467. }
  21468. if (parser.parseOptionalLess()) {
  21469. const reduction = parser.getToken().getSpelling().str();
  21470. parser.consumeToken(_.Token.bare_identifier);
  21471. result.addAttribute('reduction', reduction);
  21472. parser.parseGreater();
  21473. }
  21474. if (parser.getToken().is(_.Token.at_identifier)) {
  21475. const __spelling = parser.getToken().getSpelling().str();
  21476. parser.consumeToken(_.Token.at_identifier);
  21477. result.addAttribute('kernel', __spelling);
  21478. }
  21479. if (parser.parseOptionalLParen()) {
  21480. while (parser.getToken().isNot(_.Token.r_paren)) {
  21481. const operand = parser.parseOperand();
  21482. unresolvedOperands.push(operand);
  21483. if (parser.getToken().is(_.Token.l_square)) {
  21484. parser.skip('[');
  21485. }
  21486. if (parser.parseOptionalColon()) {
  21487. parser.consumeToken(_.Token.hash_identifier); // Skip affine map reference
  21488. }
  21489. if (!parser.parseOptionalComma()) {
  21490. break;
  21491. }
  21492. }
  21493. parser.parseRParen();
  21494. }
  21495. if (parser.parseOptionalKeyword('tile')) {
  21496. parser.parseColon();
  21497. const tile = parser.skip('[');
  21498. result.addAttribute('tile', tile);
  21499. }
  21500. parser.parseOptionalAttrDict(result.attributes);
  21501. if (parser.parseOptionalColon()) {
  21502. const funcType = parser.parseFunctionType();
  21503. if (funcType && funcType.inputs) {
  21504. parser.resolveOperands(unresolvedOperands, funcType.inputs, result.operands);
  21505. }
  21506. if (funcType && funcType.results) {
  21507. for (const resultType of funcType.results) {
  21508. result.addTypes([resultType]);
  21509. }
  21510. }
  21511. } else {
  21512. for (const unresolved of unresolvedOperands) {
  21513. parser.resolveOperand(unresolved, null, result.operands);
  21514. }
  21515. }
  21516. return true;
  21517. }
  21518. return super.parseOperation(parser, result);
  21519. }
  21520. };
  21521. _.ToyDialect = class extends _.HLODialect {
  21522. constructor(operations) {
  21523. super(operations, 'toy');
  21524. }
  21525. parseOperation(parser, result) {
  21526. if (result.op === 'toy.func') {
  21527. parser.parseFunctionOp(result, false);
  21528. return true;
  21529. }
  21530. // toy.constant: {attrs} dense<...> : type
  21531. if (result.op === 'toy.constant') {
  21532. parser.parseOptionalAttrDict(result.attributes);
  21533. const value = parser.parseAttribute();
  21534. result.addAttribute('value', value.value === undefined ? value : value.value);
  21535. result.addTypes([value.type]);
  21536. return true;
  21537. }
  21538. // toy.mul, toy.add: %lhs, %rhs : type
  21539. if (result.op === 'toy.mul' || result.op === 'toy.add') {
  21540. result.operands = parser.parseOperandList();
  21541. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21542. const types = parser.parseOptionalColonTypeList();
  21543. if (types.length > 0) {
  21544. const [type] = types;
  21545. for (const operand of result.operands) {
  21546. operand.type = type;
  21547. }
  21548. result.addTypes(types);
  21549. }
  21550. return true;
  21551. }
  21552. return super.parseOperation(parser, result);
  21553. }
  21554. };
  21555. _.SdfgDialect = class extends _.Dialect {
  21556. constructor(operations) {
  21557. super(operations, 'sdfg');
  21558. }
  21559. parseType(parser, dialect) {
  21560. const typeName = parser.parseOptionalKeyword();
  21561. if (!typeName) {
  21562. return null;
  21563. }
  21564. let type = `!${dialect}.${typeName}`;
  21565. if (typeName === 'stream' && parser.getToken().is('_')) {
  21566. parser.consumeToken('_');
  21567. const suffix = parser.getToken().getSpelling().str();
  21568. parser.consumeToken(_.Token.bare_identifier);
  21569. if (suffix === 'array') {
  21570. type += `_${suffix}`;
  21571. }
  21572. }
  21573. if (typeName === 'array' || typeName === 'stream' || typeName === 'memlet' || type.endsWith('stream_array')) {
  21574. if (parser.getToken().is(_.Token.less)) {
  21575. const content = parser.skip('<');
  21576. type += content;
  21577. }
  21578. return new _.Type(type);
  21579. }
  21580. return null;
  21581. }
  21582. parseOperation(parser, result) {
  21583. if (result.op === 'sdfg.sdfg' || result.op === 'sdfg.nested_sdfg' || result.op === 'sdir.sdfg') {
  21584. parser.parseOptionalAttrDict(result.attributes);
  21585. const inputResult = parser.parseFunctionArgumentList();
  21586. const inputs = inputResult.arguments.map((a) => a.type);
  21587. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21588. let results = [];
  21589. if (parser.parseOptionalArrow()) {
  21590. const outputResult = parser.parseFunctionArgumentList();
  21591. results = outputResult.arguments.map((a) => a.type);
  21592. }
  21593. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  21594. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21595. if (parser.getToken().is(_.Token.l_brace)) {
  21596. const region = result.addRegion();
  21597. parser.parseRegion(region);
  21598. }
  21599. return true;
  21600. }
  21601. if (result.op === 'sdfg.tasklet' || result.op === 'sdir.tasklet') {
  21602. parser.parseOptionalAttrDict(result.attributes);
  21603. if (parser.getToken().is(_.Token.at_identifier)) {
  21604. parser.parseSymbolName('sym_name', result.attributes);
  21605. }
  21606. const blockArgs = [];
  21607. if (parser.parseOptionalLParen()) {
  21608. while (!parser.parseOptionalRParen()) {
  21609. const operand = parser.parseOperand();
  21610. let blockArgName = operand;
  21611. let type = null;
  21612. if (parser.parseOptionalKeyword('as')) {
  21613. blockArgName = parser.parseOperand();
  21614. parser.parseColon();
  21615. type = parser.parseType();
  21616. } else {
  21617. parser.parseColon();
  21618. type = parser.parseType();
  21619. }
  21620. parser.resolveOperand(operand, type, result.operands);
  21621. blockArgs.push({ value: blockArgName, type });
  21622. parser.parseOptionalComma();
  21623. }
  21624. }
  21625. if (parser.parseOptionalArrow()) {
  21626. if (parser.parseOptionalLParen()) {
  21627. while (!parser.parseOptionalRParen()) {
  21628. const type = parser.parseType();
  21629. result.addTypes([type]);
  21630. parser.parseOptionalComma();
  21631. }
  21632. } else {
  21633. const type = parser.parseType();
  21634. result.addTypes([type]);
  21635. }
  21636. }
  21637. if (parser.getToken().is(_.Token.l_brace)) {
  21638. const region = result.addRegion();
  21639. parser.parseRegion(region, blockArgs);
  21640. }
  21641. return true;
  21642. }
  21643. if (result.op === 'sdfg.consume') {
  21644. parser.parseOptionalAttrDict(result.attributes);
  21645. if (parser.parseOptionalLParen()) {
  21646. while (parser.getToken().is(_.Token.percent_identifier)) {
  21647. const operand = parser.parseOperand();
  21648. let type = null;
  21649. if (parser.parseOptionalColon()) {
  21650. type = parser.parseType();
  21651. }
  21652. parser.resolveOperand(operand, type, result.operands);
  21653. if (!parser.parseOptionalComma()) {
  21654. break;
  21655. }
  21656. }
  21657. parser.parseRParen();
  21658. }
  21659. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21660. if (parser.parseOptionalArrow()) {
  21661. if (parser.parseOptionalLParen()) {
  21662. // Parse named results: (pe: %p, elem: %e)
  21663. while (!parser.parseOptionalRParen()) {
  21664. if (parser.getToken().is(_.Token.bare_identifier)) {
  21665. parser.consumeToken(_.Token.bare_identifier); // name like 'pe' or 'elem'
  21666. if (parser.parseOptionalColon()) {
  21667. parser.parseOperand(); // Parse %p or %e but don't store
  21668. result.types.push(null);
  21669. }
  21670. } else if (parser.getToken().is(_.Token.percent_identifier) || parser.getToken().is(_.Token.r_paren)) {
  21671. break;
  21672. } else {
  21673. throw new mlir.Error(`Expected named result in sdfg.consume but got '${parser.getTokenSpelling().str()}' ${parser.location()}`);
  21674. }
  21675. parser.parseOptionalComma();
  21676. }
  21677. }
  21678. }
  21679. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21680. if (parser.getToken().is(_.Token.l_brace)) {
  21681. const region = result.addRegion();
  21682. parser.parseRegion(region);
  21683. }
  21684. return true;
  21685. }
  21686. if (result.op === 'sdfg.state' || result.op === 'sdir.state') {
  21687. parser.parseOptionalAttrDict(result.attributes);
  21688. if (parser.getToken().is(_.Token.at_identifier)) {
  21689. parser.parseSymbolName('sym_name', result.attributes);
  21690. }
  21691. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21692. const region = result.addRegion();
  21693. parser.parseRegion(region);
  21694. return true;
  21695. }
  21696. if (result.op === 'sdfg.alloc' || result.op === 'sdir.alloc' || result.op === 'sdir.alloc_transient' || result.op === 'sdir.alloc_stream') {
  21697. parser.parseOptionalAttrDict(result.attributes);
  21698. const unresolvedOperands = [];
  21699. if (parser.getToken().is(_.Token.l_paren)) {
  21700. unresolvedOperands.push(...parser.parseOperandList('paren'));
  21701. }
  21702. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21703. let allocType = null;
  21704. if (parser.parseOptionalColon()) {
  21705. allocType = parser.parseType();
  21706. result.addTypes([allocType]);
  21707. }
  21708. const indexType = new _.IndexType();
  21709. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => indexType), result.operands);
  21710. return true;
  21711. }
  21712. if (result.op === 'sdfg.store' || result.op === 'sdir.store') {
  21713. parser.parseOptionalAttrDict(result.attributes);
  21714. const valueOp = parser.parseOperand();
  21715. parser.parseOptionalComma();
  21716. const arrayOp = parser.parseOperand();
  21717. const indices = [];
  21718. if (parser.parseOptionalLSquare()) {
  21719. while (parser.getToken().isNot(_.Token.r_square)) {
  21720. if (parser.getToken().is(_.Token.percent_identifier)) {
  21721. indices.push(parser.parseOperand());
  21722. } else {
  21723. parser.consumeToken();
  21724. }
  21725. if (parser.getToken().is(_.Token.comma)) {
  21726. parser.parseOptionalComma();
  21727. }
  21728. }
  21729. parser.parseOptionalRSquare();
  21730. }
  21731. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21732. if (parser.parseOptionalColon()) {
  21733. const valueType = parser.parseType();
  21734. parser.parseOptionalArrow();
  21735. const arrayType = parser.parseType();
  21736. parser.resolveOperand(valueOp, valueType, result.operands);
  21737. parser.resolveOperand(arrayOp, arrayType, result.operands);
  21738. const indexType = new _.IndexType();
  21739. parser.resolveOperands(indices, indices.map(() => indexType), result.operands);
  21740. } else {
  21741. parser.resolveOperand(valueOp, null, result.operands);
  21742. parser.resolveOperand(arrayOp, null, result.operands);
  21743. parser.resolveOperands(indices, indices.map(() => null), result.operands);
  21744. }
  21745. return true;
  21746. }
  21747. if (result.op === 'sdfg.load' || result.op === 'sdir.load') {
  21748. parser.parseOptionalAttrDict(result.attributes);
  21749. const arrayOp = parser.parseOperand();
  21750. const indices = [];
  21751. if (parser.parseOptionalLSquare()) {
  21752. while (parser.getToken().isNot(_.Token.r_square)) {
  21753. if (parser.getToken().is(_.Token.percent_identifier)) {
  21754. indices.push(parser.parseOperand());
  21755. } else {
  21756. parser.consumeToken();
  21757. }
  21758. if (parser.getToken().is(_.Token.comma)) {
  21759. parser.parseOptionalComma();
  21760. }
  21761. }
  21762. parser.parseOptionalRSquare();
  21763. }
  21764. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21765. if (parser.parseOptionalColon()) {
  21766. const arrayType = parser.parseType();
  21767. parser.parseOptionalArrow();
  21768. const resultType = parser.parseType();
  21769. parser.resolveOperand(arrayOp, arrayType, result.operands);
  21770. const indexType = new _.IndexType();
  21771. parser.resolveOperands(indices, indices.map(() => indexType), result.operands);
  21772. result.addTypes([resultType]);
  21773. } else {
  21774. parser.resolveOperand(arrayOp, null, result.operands);
  21775. parser.resolveOperands(indices, indices.map(() => null), result.operands);
  21776. }
  21777. return true;
  21778. }
  21779. if (result.op === 'sdfg.map' || result.op === 'sdir.map') {
  21780. parser.parseOptionalAttrDict(result.attributes);
  21781. const params = [];
  21782. if (parser.parseOptionalLParen()) {
  21783. while (!parser.parseOptionalRParen()) {
  21784. if (parser.getToken().is(_.Token.percent_identifier)) {
  21785. const param = parser.parseOperand();
  21786. params.push(param);
  21787. }
  21788. if (parser.getToken().is(_.Token.comma)) {
  21789. parser.parseOptionalComma();
  21790. }
  21791. }
  21792. }
  21793. if (parser.parseOptionalEqual()) {
  21794. parser.skip('(');
  21795. }
  21796. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'to') {
  21797. parser.parseOptionalKeyword('to');
  21798. parser.skip('(');
  21799. }
  21800. if (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'step') {
  21801. parser.parseOptionalKeyword('step');
  21802. parser.skip('(');
  21803. }
  21804. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21805. if (parser.getToken().is(_.Token.l_brace)) {
  21806. const region = result.addRegion();
  21807. parser.parseRegion(region);
  21808. }
  21809. return true;
  21810. }
  21811. if (result.op === 'sdir.consume') {
  21812. parser.parseOptionalAttrDict(result.attributes);
  21813. if (parser.parseOptionalLParen()) {
  21814. while (parser.getToken().is(_.Token.percent_identifier)) {
  21815. const operand = parser.parseOperand();
  21816. let type = null;
  21817. if (parser.parseOptionalColon()) {
  21818. type = parser.parseType();
  21819. }
  21820. parser.resolveOperand(operand, type, result.operands);
  21821. if (!parser.parseOptionalComma()) {
  21822. break;
  21823. }
  21824. }
  21825. parser.parseRParen();
  21826. }
  21827. if (parser.parseOptionalArrow()) {
  21828. if (parser.parseOptionalLParen()) {
  21829. while (!parser.parseOptionalRParen()) {
  21830. parser.consumeToken();
  21831. }
  21832. }
  21833. }
  21834. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21835. if (parser.getToken().is(_.Token.l_brace)) {
  21836. const region = result.addRegion();
  21837. parser.parseRegion(region);
  21838. }
  21839. return true;
  21840. }
  21841. if (result.op === 'sdfg.edge' || result.op === 'sdir.edge') {
  21842. parser.parseOptionalAttrDict(result.attributes);
  21843. if (parser.parseOptionalLParen()) {
  21844. while (parser.getToken().isNot(_.Token.r_paren)) {
  21845. if (parser.getToken().is(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.percent_identifier)) {
  21846. parser.consumeToken(_.Token.bare_identifier); // label like 'ref'
  21847. parser.parseColon();
  21848. }
  21849. if (parser.getToken().is(_.Token.percent_identifier)) {
  21850. const operand = parser.parseOperand();
  21851. let type = null;
  21852. if (parser.parseOptionalColon()) {
  21853. type = parser.parseType();
  21854. }
  21855. parser.resolveOperand(operand, type, result.operands);
  21856. }
  21857. if (!parser.parseOptionalComma()) {
  21858. break;
  21859. }
  21860. }
  21861. parser.parseRParen();
  21862. }
  21863. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21864. if (parser.getToken().is(_.Token.at_identifier)) {
  21865. const src = parser.getToken().getSpelling().str();
  21866. parser.consumeToken(_.Token.at_identifier);
  21867. result.addAttribute('src', src);
  21868. }
  21869. parser.parseOptionalArrow();
  21870. if (parser.getToken().is(_.Token.at_identifier)) {
  21871. const dst = parser.getToken().getSpelling().str();
  21872. parser.consumeToken(_.Token.at_identifier);
  21873. result.addAttribute('dst', dst);
  21874. }
  21875. return true;
  21876. }
  21877. if (result.op === 'sdfg.sym' || result.op === 'sdir.sym') {
  21878. if (parser.parseOptionalLParen()) {
  21879. const expr = parser.getToken().getSpelling().str();
  21880. parser.consumeToken(_.Token.string);
  21881. result.addAttribute('expr', expr);
  21882. parser.parseOptionalRParen();
  21883. }
  21884. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  21885. if (parser.parseOptionalColon()) {
  21886. const type = parser.parseType();
  21887. result.addTypes([type]);
  21888. }
  21889. return true;
  21890. }
  21891. if (result.op === 'sdfg.copy' || result.op === 'sdir.copy') {
  21892. parser.parseOptionalAttrDict(result.attributes);
  21893. const unresolvedSrc = parser.parseOperandList('none');
  21894. const unresolvedDst = [];
  21895. if (parser.parseOptionalArrow()) {
  21896. unresolvedDst.push(...parser.parseOperandList('none'));
  21897. }
  21898. if (parser.parseOptionalColon()) {
  21899. const type = parser.parseType();
  21900. const allUnresolved = unresolvedSrc.concat(unresolvedDst);
  21901. parser.resolveOperands(allUnresolved, allUnresolved.map(() => type), result.operands);
  21902. } else {
  21903. const allUnresolved = unresolvedSrc.concat(unresolvedDst);
  21904. parser.resolveOperands(allUnresolved, allUnresolved.map(() => null), result.operands);
  21905. }
  21906. return true;
  21907. }
  21908. if (result.op === 'sdfg.libcall' || result.op === 'sdir.libcall') {
  21909. parser.parseOptionalAttrDict(result.attributes);
  21910. if (parser.getToken().is(_.Token.string)) {
  21911. const libname = parser.getToken().getSpelling().str();
  21912. parser.consumeToken(_.Token.string);
  21913. result.addAttribute('libname', libname);
  21914. }
  21915. const unresolvedOperands = parser.parseOperandList('paren');
  21916. const types = [];
  21917. if (parser.parseOptionalColon()) {
  21918. if (parser.parseOptionalLParen()) {
  21919. while (!parser.parseOptionalRParen()) {
  21920. types.push(parser.parseType());
  21921. parser.parseOptionalComma();
  21922. }
  21923. }
  21924. if (parser.parseOptionalArrow()) {
  21925. const resultType = parser.parseType();
  21926. result.addTypes([resultType]);
  21927. }
  21928. }
  21929. parser.resolveOperands(unresolvedOperands, types.length > 0 ? types : unresolvedOperands.map(() => null), result.operands);
  21930. return true;
  21931. }
  21932. if (result.op === 'sdfg.get_access' || result.op === 'sdir.get_access') {
  21933. let unresolvedOperand = null;
  21934. if (parser.getToken().is(_.Token.percent_identifier)) {
  21935. unresolvedOperand = parser.parseOperand();
  21936. }
  21937. if (parser.parseOptionalColon()) {
  21938. const inputType = parser.parseType();
  21939. if (unresolvedOperand) {
  21940. parser.resolveOperand(unresolvedOperand, inputType, result.operands);
  21941. }
  21942. if (parser.parseOptionalArrow()) {
  21943. const resultType = parser.parseType();
  21944. result.addTypes([resultType]);
  21945. }
  21946. } else if (unresolvedOperand) {
  21947. // No explicit type - try to resolve operand and infer type from its definition
  21948. parser.resolveOperand(unresolvedOperand, null, result.operands);
  21949. // If operand was resolved with a type, use it as result type
  21950. if (result.operands.length > 0 && result.operands[0].type) {
  21951. result.addTypes([result.operands[0].type]);
  21952. } else {
  21953. // Fallback: use a generic memref type
  21954. result.addTypes([new _.Type('memref<*xf32>')]);
  21955. }
  21956. }
  21957. return true;
  21958. }
  21959. if (result.op === 'sdir.call') {
  21960. const callee = parser.parseOptionalSymbolName();
  21961. if (callee) {
  21962. result.addAttribute('callee', callee);
  21963. }
  21964. if (parser.getToken().is(_.Token.l_paren)) {
  21965. const unresolvedOperands = parser.parseOperandList('paren');
  21966. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  21967. }
  21968. if (parser.parseOptionalColon()) {
  21969. if (parser.parseOptionalLParen()) {
  21970. while (!parser.parseOptionalRParen()) {
  21971. parser.parseType();
  21972. parser.parseOptionalComma();
  21973. }
  21974. }
  21975. if (parser.parseOptionalArrow()) {
  21976. const resultType = parser.parseType();
  21977. result.addTypes([resultType]);
  21978. }
  21979. }
  21980. return true;
  21981. }
  21982. if (result.op === 'sdfg.alloc_symbol' || result.op === 'sdir.alloc_symbol') {
  21983. if (parser.parseOptionalLParen()) {
  21984. const sym = parser.getToken().getSpelling().str();
  21985. parser.consumeToken(_.Token.string);
  21986. result.addAttribute('sym', sym);
  21987. parser.parseOptionalRParen();
  21988. }
  21989. return true;
  21990. }
  21991. if (result.op === 'sdfg.return') {
  21992. if (parser.getToken().is(_.Token.percent_identifier)) {
  21993. const unresolvedOperands = parser.parseOperandList('none');
  21994. const types = parser.parseOptionalColonTypeList();
  21995. parser.resolveOperands(unresolvedOperands, types, result.operands);
  21996. }
  21997. return true;
  21998. }
  21999. if (result.op === 'sdfg.stream_push' || result.op === 'sdir.stream_push') {
  22000. parser.parseOptionalAttrDict(result.attributes);
  22001. const unresolvedValue = parser.parseOperand();
  22002. parser.parseOptionalComma();
  22003. const unresolvedStream = parser.parseOperand();
  22004. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22005. let valueType = null;
  22006. let streamType = null;
  22007. if (parser.parseOptionalColon()) {
  22008. valueType = parser.parseType();
  22009. parser.parseOptionalArrow();
  22010. streamType = parser.parseType();
  22011. }
  22012. parser.resolveOperand(unresolvedValue, valueType, result.operands);
  22013. parser.resolveOperand(unresolvedStream, streamType, result.operands);
  22014. return true;
  22015. }
  22016. if (result.op === 'sdfg.stream_pop' || result.op === 'sdir.stream_pop') {
  22017. parser.parseOptionalAttrDict(result.attributes);
  22018. const unresolvedStream = parser.parseOperand();
  22019. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22020. let streamType = null;
  22021. if (parser.parseOptionalColon()) {
  22022. streamType = parser.parseType();
  22023. parser.parseOptionalArrow();
  22024. const resultType = parser.parseType();
  22025. result.addTypes([resultType]);
  22026. }
  22027. parser.resolveOperand(unresolvedStream, streamType, result.operands);
  22028. return true;
  22029. }
  22030. if (result.op === 'sdfg.stream_length' || result.op === 'sdir.stream_length') {
  22031. parser.parseOptionalAttrDict(result.attributes);
  22032. const unresolvedStream = parser.parseOperand();
  22033. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22034. let streamType = null;
  22035. if (parser.parseOptionalColon()) {
  22036. streamType = parser.parseType();
  22037. parser.parseOptionalArrow();
  22038. const resultType = parser.parseType();
  22039. result.addTypes([resultType]);
  22040. }
  22041. parser.resolveOperand(unresolvedStream, streamType, result.operands);
  22042. return true;
  22043. }
  22044. if (result.op === 'sdfg.view_cast' || result.op === 'sdir.view_cast') {
  22045. parser.parseOptionalAttrDict(result.attributes);
  22046. const unresolvedInput = parser.parseOperand();
  22047. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22048. let inputType = null;
  22049. if (parser.parseOptionalColon()) {
  22050. inputType = parser.parseType();
  22051. parser.parseOptionalArrow();
  22052. const resultType = parser.parseType();
  22053. result.addTypes([resultType]);
  22054. }
  22055. parser.resolveOperand(unresolvedInput, inputType, result.operands);
  22056. return true;
  22057. }
  22058. if (result.op === 'sdfg.subview' || result.op === 'sdir.subview') {
  22059. parser.parseOptionalAttrDict(result.attributes);
  22060. const unresolvedInput = parser.parseOperand();
  22061. while (parser.parseOptionalLSquare()) {
  22062. while (!parser.parseOptionalRSquare()) {
  22063. parser.consumeToken();
  22064. }
  22065. }
  22066. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22067. let inputType = null;
  22068. if (parser.parseOptionalColon()) {
  22069. inputType = parser.parseType();
  22070. parser.parseOptionalArrow();
  22071. const resultType = parser.parseType();
  22072. result.addTypes([resultType]);
  22073. }
  22074. parser.resolveOperand(unresolvedInput, inputType, result.operands);
  22075. return true;
  22076. }
  22077. return super.parseOperation(parser, result);
  22078. }
  22079. };
  22080. _.TFLDialect = class extends _.Dialect {
  22081. constructor(operations) {
  22082. super(operations, 'tfl');
  22083. // Operations that use parseOneResultSameOperandTypeOp in tfl_ops.cc
  22084. this._binaryOps = new Set([
  22085. 'add', 'sub', 'mul', 'div', 'floor_div', 'pow', 'squared_difference',
  22086. 'less', 'less_equal', 'greater', 'greater_equal', 'not_equal',
  22087. 'logical_and', 'logical_or'
  22088. ]);
  22089. }
  22090. parseOperation(parser, result) {
  22091. const opKind = result.op.substring('tfl.'.length);
  22092. if (opKind === 'control_node') {
  22093. if (parser.parseOptionalLParen()) {
  22094. const unresolvedOperands = parser.parseOperandList('none');
  22095. parser.parseRParen();
  22096. // control_node operands don't have types parsed inline
  22097. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  22098. }
  22099. if (parser.parseOptionalKeyword('controls')) {
  22100. const region = { blocks: [{ operations: [] }] };
  22101. const innerOp = parser.parseGenericOperation();
  22102. region.blocks[0].operations.push(innerOp);
  22103. result.regions.push(region);
  22104. // Result types are inferred from inner op results + control type
  22105. for (const opResult of innerOp.results) {
  22106. result.addTypes([opResult.type]);
  22107. }
  22108. result.addTypes([new _.Type('!tfl.control')]);
  22109. } else if (parser.getToken().is(_.Token.l_brace)) {
  22110. const region = result.addRegion();
  22111. parser.parseRegion(region);
  22112. // Result types from yield terminator + control type
  22113. const block = region.blocks[region.blocks.length - 1];
  22114. const yieldOp = block.operations[block.operations.length - 1];
  22115. if (yieldOp && yieldOp.operands) {
  22116. for (const operand of yieldOp.operands) {
  22117. result.addTypes([operand.type]);
  22118. }
  22119. }
  22120. result.addTypes([new _.Type('!tfl.control')]);
  22121. }
  22122. parser.parseOptionalAttrDict(result.attributes);
  22123. return true;
  22124. }
  22125. if (this._binaryOps.has(opKind)) {
  22126. // Or: (operands) <properties> : fn-type (generic form)
  22127. if (parser.getToken().is(_.Token.l_paren)) {
  22128. parser.parseLParen();
  22129. const unresolvedOperands = parser.parseOperandList('none');
  22130. parser.parseRParen();
  22131. if (parser.parseOptionalLess()) {
  22132. result.propertiesAttr = parser.parseAttribute();
  22133. parser.parseGreater();
  22134. }
  22135. parser.parseOptionalAttrDict(result.attributes);
  22136. if (parser.parseOptionalColon()) {
  22137. const fnType = parser.parseType();
  22138. if (fnType instanceof _.FunctionType) {
  22139. parser.resolveOperands(unresolvedOperands, fnType.inputs, result.operands);
  22140. result.addTypes(fnType.results);
  22141. } else {
  22142. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => fnType), result.operands);
  22143. result.addTypes([fnType]);
  22144. }
  22145. } else {
  22146. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  22147. }
  22148. return true;
  22149. }
  22150. // Compact form: %a, %b attr-dict : type
  22151. const unresolvedOperands = parser.parseOperandList('none');
  22152. parser.parseOptionalAttrDict(result.attributes);
  22153. if (parser.parseOptionalColon()) {
  22154. const type = parser.parseType();
  22155. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => type), result.operands);
  22156. result.addTypes([type]);
  22157. } else {
  22158. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  22159. }
  22160. return true;
  22161. }
  22162. return super.parseOperation(parser, result);
  22163. }
  22164. };
  22165. _.TFDialect = class extends _.Dialect {
  22166. constructor(operations) {
  22167. super(operations, 'tf');
  22168. }
  22169. parseType(parser, dialect) {
  22170. const typeName = parser.parseOptionalKeyword();
  22171. if (!typeName) {
  22172. return null;
  22173. }
  22174. let type = `!${dialect}.${typeName}`;
  22175. if (typeName === 'resource' || typeName === 'variant') {
  22176. if (parser.getToken().is(_.Token.less)) {
  22177. const content = parser.skip('<');
  22178. type += content;
  22179. }
  22180. return new _.Type(type);
  22181. }
  22182. if (typeName === 'string' || typeName === 'control') {
  22183. return new _.Type(type);
  22184. }
  22185. return null;
  22186. }
  22187. };
  22188. _.TFTypeDialect = class extends _.Dialect {
  22189. constructor(operations) {
  22190. super(operations, 'tf_type');
  22191. this.simpleTypes = new Set([
  22192. 'string', 'qint8', 'qint16', 'qint32', 'quint8', 'quint16',
  22193. 'f32ref', 'f64ref', 'uint4ref', 'int4ref', 'uint8ref', 'int8ref',
  22194. 'uint16ref', 'int16ref', 'uint32ref', 'int32ref', 'uint64ref', 'int64ref',
  22195. 'stringref', 'boolref', 'quint8ref', 'qint8ref', 'quint16ref', 'qint16ref',
  22196. 'qint32ref', 'bfloat16ref', 'complex64ref', 'complex128ref', 'halfref',
  22197. 'resourceref', 'variantref',
  22198. 'float8e4m3fnref', 'float8e5m2ref', 'float8e4m3fnuzref',
  22199. 'float8e4m3b11fnuzref', 'float8e5m2fnuzref'
  22200. ]);
  22201. }
  22202. parseType(parser, dialect) {
  22203. const typeName = parser.parseOptionalKeyword();
  22204. if (!typeName) {
  22205. return null;
  22206. }
  22207. let type = `!${dialect}.${typeName}`;
  22208. // Handle parametrized types like resource<>, variant<>, resource_handle<>
  22209. if (typeName === 'resource' || typeName === 'variant' || typeName === 'resource_handle') {
  22210. if (parser.parseOptionalLess()) {
  22211. const subtypes = [];
  22212. while (parser.getToken().isNot(_.Token.greater)) {
  22213. subtypes.push(parser.parseType());
  22214. parser.parseOptionalComma();
  22215. }
  22216. parser.parseGreater();
  22217. return new _.Type(`${type}<${subtypes.join(', ')}>`);
  22218. }
  22219. return new _.Type(type);
  22220. }
  22221. if (this.simpleTypes.has(typeName)) {
  22222. return new _.Type(type);
  22223. }
  22224. // Fallback for unknown tf_type types
  22225. if (parser.getToken().is(_.Token.less)) {
  22226. type += parser.skip('<');
  22227. }
  22228. return new _.Type(type);
  22229. }
  22230. };
  22231. _.TransformDialect = class extends _.Dialect {
  22232. constructor(operations) {
  22233. super(operations, 'transform');
  22234. this.registerCustomDirective('PackedOrDynamicIndexList', this.parsePackedOrDynamicIndexList.bind(this));
  22235. this.registerCustomDirective('SemiFunctionType', this.parseSemiFunctionType.bind(this));
  22236. this.registerCustomDirective('SequenceOpOperands', this.parseSequenceOpOperands.bind(this));
  22237. this.registerCustomDirective('ForeachMatchSymbols', this.parseForeachMatchSymbols.bind(this));
  22238. this.registerCustomDirective('TransformMatchDims', this.parseTransformMatchDims.bind(this));
  22239. this.registerCustomDirective('ApplyRegisteredPassOptions', this.parseApplyRegisteredPassOptions.bind(this));
  22240. this.registerCustomDirective('AlternativesOpSelectedRegion', this.parseAlternativesOpSelectedRegion.bind(this));
  22241. this.registerCustomDirective('ContinuousTileSizeTypes', this.parseContinuousTileSizeTypes.bind(this));
  22242. this.registerCustomDirective('MultitileSizesTypes', this.parseMultitileSizesTypes.bind(this));
  22243. }
  22244. parseOperation(parser, result) {
  22245. if (result.op === 'transform.named_sequence') {
  22246. return this.parseNamedSequenceOp(parser, result);
  22247. }
  22248. // C++-only operation: transform.test_transform_op ["message"]
  22249. // Defined in mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp
  22250. if (result.op === 'transform.test_transform_op') {
  22251. if (parser.getToken().is(_.Token.string)) {
  22252. const message = parser.getToken().getSpelling().str();
  22253. parser.consumeToken(_.Token.string);
  22254. result.addAttribute('message', message);
  22255. }
  22256. return true;
  22257. }
  22258. // LinalgTransformOps.cpp:3009 SplitOp::parse
  22259. if (result.op === 'transform.structured.split') {
  22260. const unresolvedTarget = parser.parseOperand();
  22261. parser.parseKeyword('after');
  22262. let unresolvedDynamicChunk = null;
  22263. if (parser.getToken().is(_.Token.percent_identifier)) {
  22264. unresolvedDynamicChunk = parser.parseOperand();
  22265. } else {
  22266. const staticChunkSizes = parser.parseInteger();
  22267. result.addAttribute('static_chunk_sizes', staticChunkSizes);
  22268. }
  22269. parser.parseOptionalAttrDict(result.attributes);
  22270. parser.parseColon();
  22271. const targetType = parser.parseType();
  22272. parser.resolveOperand(unresolvedTarget, targetType, result.operands);
  22273. result.addTypes([targetType]);
  22274. if (unresolvedDynamicChunk && parser.parseOptionalComma()) {
  22275. const chunkType = parser.parseType();
  22276. parser.resolveOperand(unresolvedDynamicChunk, chunkType, result.operands);
  22277. } else if (unresolvedDynamicChunk) {
  22278. // Default to index type if chunk type not specified
  22279. parser.resolveOperand(unresolvedDynamicChunk, null, result.operands);
  22280. }
  22281. return true;
  22282. }
  22283. return super.parseOperation(parser, result);
  22284. }
  22285. parseSequenceOpOperands(parser, op /*, args */) {
  22286. const unresolvedOperands = [];
  22287. if (parser.getToken().is(_.Token.percent_identifier)) {
  22288. unresolvedOperands.push(parser.parseOperand());
  22289. if (parser.parseOptionalComma()) {
  22290. while (parser.getToken().is(_.Token.percent_identifier)) {
  22291. unresolvedOperands.push(parser.parseOperand());
  22292. if (!parser.parseOptionalComma()) {
  22293. break;
  22294. }
  22295. }
  22296. }
  22297. }
  22298. if (parser.parseOptionalColon()) {
  22299. parser.parseOptionalLParen();
  22300. const types = parser.parseTypeListNoParens();
  22301. parser.resolveOperands(unresolvedOperands, types, op.operands);
  22302. parser.parseOptionalRParen();
  22303. } else {
  22304. for (const unresolved of unresolvedOperands) {
  22305. parser.resolveOperand(unresolved, null, op.operands);
  22306. }
  22307. }
  22308. }
  22309. parseForeachMatchSymbols(parser, op, matchersAttr, actionsAttr) {
  22310. const matchers = [];
  22311. const actions = [];
  22312. do {
  22313. const matcher = parser.getToken().getSpelling().str();
  22314. parser.consumeToken(_.Token.at_identifier);
  22315. parser.parseArrow();
  22316. const action = parser.getToken().getSpelling().str();
  22317. parser.consumeToken(_.Token.at_identifier);
  22318. matchers.push(matcher);
  22319. actions.push(action);
  22320. } while (parser.parseOptionalComma());
  22321. op.addAttribute(matchersAttr, matchers);
  22322. op.addAttribute(actionsAttr, actions);
  22323. }
  22324. parseTransformMatchDims(parser, op, dimsAttr, invertedAttr, allAttr) {
  22325. if (parser.parseOptionalKeyword('all')) {
  22326. op.addAttribute(allAttr, true);
  22327. return;
  22328. }
  22329. const isInverted = parser.parseOptionalKeyword('except');
  22330. if (isInverted) {
  22331. parser.parseLParen();
  22332. }
  22333. const dims = [];
  22334. do {
  22335. const value = parser.parseOptionalInteger();
  22336. if (value !== null) {
  22337. dims.push(value);
  22338. }
  22339. } while (parser.parseOptionalComma());
  22340. if (isInverted) {
  22341. parser.parseRParen();
  22342. op.addAttribute(invertedAttr, true);
  22343. }
  22344. op.addAttribute(dimsAttr, dims);
  22345. }
  22346. parseType(parser, dialect) {
  22347. const typeName = parser.parseOptionalKeyword();
  22348. if (!typeName) {
  22349. return null;
  22350. }
  22351. let type = `!${dialect}.${typeName}`;
  22352. if (typeName === 'any' && parser.getToken().is('_')) {
  22353. parser.consumeToken('_');
  22354. const suffix = parser.getToken().getSpelling().str();
  22355. parser.consumeToken(_.Token.bare_identifier);
  22356. type += `_${suffix}`;
  22357. }
  22358. if (parser.getToken().is(_.Token.less)) {
  22359. const content = parser.skip('<');
  22360. type += content;
  22361. }
  22362. return new _.Type(type);
  22363. }
  22364. parseNamedSequenceOp(parser, result) {
  22365. parser.parseOptionalVisibilityKeyword(result.attributes);
  22366. parser.parseSymbolName('sym_name', result.attributes);
  22367. const argResult = parser.parseFunctionArgumentList();
  22368. const inputs = argResult.arguments.map((a) => a.type);
  22369. const results = [];
  22370. const resultAttrs = [];
  22371. if (parser.parseOptionalArrow()) {
  22372. parser.parseFunctionResultList(results, resultAttrs);
  22373. }
  22374. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType(inputs, results)));
  22375. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22376. if (parser.getToken().is(_.Token.l_brace)) {
  22377. const region = result.addRegion();
  22378. parser.parseRegion(region);
  22379. }
  22380. return true;
  22381. }
  22382. parseSemiFunctionType(parser, op /* , args */) {
  22383. const hasLParen = parser.parseOptionalLParen();
  22384. const argType = parser.parseType();
  22385. if (op.operands.length > 0) {
  22386. op.operands[0].type = argType;
  22387. }
  22388. if (!hasLParen) {
  22389. return;
  22390. }
  22391. parser.parseRParen();
  22392. parser.parseArrow();
  22393. if (parser.parseOptionalLParen()) {
  22394. let idx = 0;
  22395. while (parser.getToken().isNot(_.Token.r_paren)) {
  22396. const type = parser.parseType();
  22397. if (idx < op.types.length) {
  22398. op.types[idx] = type;
  22399. } else {
  22400. op.addTypes([type]);
  22401. }
  22402. idx++;
  22403. if (!parser.parseOptionalComma()) {
  22404. break;
  22405. }
  22406. }
  22407. parser.parseRParen();
  22408. } else {
  22409. const type = parser.parseType();
  22410. if (op.types.length > 0) {
  22411. op.types[0] = type;
  22412. } else {
  22413. op.addTypes([type]);
  22414. }
  22415. }
  22416. }
  22417. parsePackedOrDynamicIndexList(parser, op, packedName, dynamicName, staticAttrName) {
  22418. const dynamicOperands = [];
  22419. const dynamicTypes = [];
  22420. const staticValues = [];
  22421. let packedOperand = null;
  22422. // Check for packed syntax: *(%operand)
  22423. if (parser.consumeIf(_.Token.star)) {
  22424. parser.parseLParen();
  22425. if (parser.getToken().is(_.Token.percent_identifier)) {
  22426. packedOperand = parser.parseOperand();
  22427. }
  22428. parser.parseRParen();
  22429. } else if (parser.parseOptionalLSquare()) {
  22430. // List syntax: [int, %operand, int, ...]
  22431. while (parser.getToken().isNot(_.Token.r_square)) {
  22432. if (parser.getToken().is(_.Token.percent_identifier)) {
  22433. const value = parser.parseOperand();
  22434. dynamicOperands.push(value);
  22435. staticValues.push(-9223372036854775808); // ShapedType::kDynamic
  22436. let type = null;
  22437. if (parser.parseOptionalColon()) {
  22438. type = parser.parseType();
  22439. }
  22440. dynamicTypes.push(type);
  22441. } else if (parser.getToken().is(_.Token.integer) || parser.getToken().is('number')) {
  22442. const intVal = parseInt(parser.getToken().getSpelling().str(), 10);
  22443. parser.consumeToken();
  22444. staticValues.push(intVal);
  22445. } else {
  22446. break;
  22447. }
  22448. parser.parseOptionalComma();
  22449. }
  22450. parser.parseRSquare();
  22451. }
  22452. if (packedOperand && packedName) {
  22453. parser.resolveOperand(packedOperand, null, op.operands);
  22454. }
  22455. if (dynamicName) {
  22456. for (let i = 0; i < dynamicOperands.length; i++) {
  22457. const type = i < dynamicTypes.length ? dynamicTypes[i] : null;
  22458. parser.resolveOperand(dynamicOperands[i], type, op.operands);
  22459. }
  22460. }
  22461. if (staticAttrName && staticValues.length > 0) {
  22462. op.addAttribute(staticAttrName, staticValues);
  22463. }
  22464. }
  22465. parseContinuousTileSizeTypes(parser, result, targetTypes, tileSizesTypes, chunkSizesTypes) {
  22466. const funcType = parser.parseType();
  22467. if (funcType instanceof _.FunctionType) {
  22468. if (funcType.inputs.length !== 1 || funcType.results.length !== 1) {
  22469. throw new mlir.Error(`Expected a trailing functional type with one argument and one result.`);
  22470. }
  22471. targetTypes.push(funcType.inputs[0]);
  22472. tileSizesTypes.push(funcType.results[0]);
  22473. chunkSizesTypes.push(funcType.results[0]);
  22474. }
  22475. }
  22476. parseMultitileSizesTypes(parser, result, targetTypes, lowSizeTypes, highSizeTypes, splitPointTypes) {
  22477. const funcType = parser.parseType();
  22478. if (funcType instanceof _.FunctionType) {
  22479. if (funcType.inputs.length !== 1 || funcType.results.length !== 1) {
  22480. throw new mlir.Error(`Expected a trailing functional type with one argument and one result.`);
  22481. }
  22482. targetTypes.push(funcType.inputs[0]);
  22483. lowSizeTypes.push(funcType.results[0]);
  22484. highSizeTypes.push(funcType.results[0]);
  22485. splitPointTypes.push(funcType.results[0]);
  22486. }
  22487. }
  22488. parseApplyRegisteredPassOptions(parser, result) {
  22489. if (!parser.parseOptionalLBrace()) {
  22490. return;
  22491. }
  22492. const options = {};
  22493. while (parser.getToken().isNot(_.Token.r_brace)) {
  22494. let key = null;
  22495. if (parser.getToken().is(_.Token.string)) {
  22496. key = parser.getToken().getSpelling().str();
  22497. parser.consumeToken(_.Token.string);
  22498. } else {
  22499. key = parser.parseOptionalKeyword();
  22500. }
  22501. parser.parseEqual();
  22502. if (parser.getToken().is(_.Token.percent_identifier)) {
  22503. const operand = parser.parseOperand();
  22504. parser.resolveOperand(operand, null, result.operands);
  22505. options[key] = `#transform.param_operand<${result.operands.length - 1}>`;
  22506. } else if (parser.getToken().is(_.Token.l_square)) {
  22507. parser.parseOptionalLSquare();
  22508. const arr = [];
  22509. while (parser.getToken().isNot(_.Token.r_square)) {
  22510. if (parser.getToken().is(_.Token.percent_identifier)) {
  22511. const operand = parser.parseOperand();
  22512. parser.resolveOperand(operand, null, result.operands);
  22513. arr.push(`#transform.param_operand<${result.operands.length - 1}>`);
  22514. } else {
  22515. const val = parser.parseAttribute();
  22516. arr.push(val);
  22517. }
  22518. parser.parseOptionalComma();
  22519. }
  22520. parser.parseRSquare();
  22521. options[key] = arr;
  22522. } else {
  22523. const value = parser.parseAttribute();
  22524. options[key] = value;
  22525. }
  22526. parser.parseOptionalComma();
  22527. }
  22528. parser.parseRBrace();
  22529. result.addAttribute('options', options);
  22530. }
  22531. parseAlternativesOpSelectedRegion(parser, result) {
  22532. if (parser.getToken().is(_.Token.integer)) {
  22533. const value = parser.parseInteger();
  22534. result.addAttribute('selected_region_attr', value);
  22535. } else if (parser.getToken().is(_.Token.percent_identifier)) {
  22536. const operand = parser.parseOperand();
  22537. parser.resolveOperand(operand, null, result.operands);
  22538. }
  22539. }
  22540. };
  22541. _.TestDialect = class extends _.Dialect {
  22542. constructor(operations) {
  22543. super(operations, 'test');
  22544. this.blobManager = new Map();
  22545. this.registerCustomDirective('CustomOptionalOperand', this.parseCustomOptionalOperand.bind(this));
  22546. this.registerCustomDirective('CustomDirectiveOperands', this.parseCustomDirectiveOperands.bind(this));
  22547. this.registerCustomDirective('CustomDirectiveOperandsAndTypes', this.parseCustomDirectiveOperandsAndTypes.bind(this));
  22548. this.registerCustomDirective('CustomDirectiveResults', this.parseCustomDirectiveResults.bind(this));
  22549. this.registerCustomDirective('CustomDirectiveWithTypeRefs', this.parseCustomDirectiveWithTypeRefs.bind(this));
  22550. this.registerCustomDirective('CustomDirectiveRegions', this.parseCustomDirectiveRegions.bind(this));
  22551. this.registerCustomDirective('CustomDirectiveSuccessors', this.parseCustomDirectiveSuccessors.bind(this));
  22552. this.registerCustomDirective('CustomDirectiveAttrDict', this.parseCustomDirectiveAttrDict.bind(this));
  22553. this.registerCustomDirective('CustomDirectiveAttributes', this.parseCustomDirectiveAttributes.bind(this));
  22554. this.registerCustomDirective('CustomDirectiveSpacing', this.parseCustomDirectiveSpacing.bind(this));
  22555. this.registerCustomDirective('CustomDirectiveOptionalOperandRef', this.parseCustomDirectiveOptionalOperandRef.bind(this));
  22556. this.registerCustomDirective('UsingPropertyInCustom', this.parseUsingPropertyInCustom.bind(this));
  22557. this.registerCustomDirective('IntProperty', this.parseIntProperty.bind(this));
  22558. this.registerCustomDirective('SumProperty', this.parseSumProperty.bind(this));
  22559. this.registerCustomDirective('SwitchCases', this.parseSwitchCases.bind(this));
  22560. this.registerCustomDirective('DimensionList', this.parseDimensionList.bind(this));
  22561. this.registerCustomDirective('OptionalCustomParser', this.parseOptionalCustomParser.bind(this));
  22562. this.registerCustomDirective('OptionalLoc', this.parseOptionalLoc.bind(this));
  22563. this.registerCustomDirective('DummyRegionRef', this.parseDummyRegionRef.bind(this));
  22564. this.registerCustomDirective('DummySuccessorRef', this.parseDummySuccessorRef.bind(this));
  22565. this.registerCustomType('CompoundNestedOuterType', this.parseCompoundNestedOuterType.bind(this));
  22566. this.registerCustomType('CompoundNestedInnerType', this.parseCompoundNestedInnerType.bind(this));
  22567. this.registerCustomType('CompoundTypeA', this.parseCompoundTypeA.bind(this));
  22568. this.registerCustomAttribute('TestBitEnumAttr', this.parseEnumFlagsAngleBracketComma.bind(this));
  22569. this.registerCustomAttribute('TestBitEnumVerticalBarAttr', this.parseEnumFlagsAngleBracketPipe.bind(this));
  22570. this.registerCustomAttribute('TestEnumAttr', this.parseTestEnumAttr.bind(this));
  22571. this.registerCustomAttribute('TestEnumProp', this.parseTestEnumAttr.bind(this));
  22572. this.registerCustomAttribute('TestEnumPropAttrForm', this.parseTestEnumPropAttrForm.bind(this));
  22573. this.registerCustomAttribute('TestBitEnumProp', this.parseTestBitEnumProp.bind(this));
  22574. this.registerCustomAttribute('TestBitEnumPropNamed', this.parseTestBitEnumPropNamed.bind(this));
  22575. this.registerCustomAttribute('TestArrayOfUglyAttrs', this.parseTestArrayOfUglyAttrs.bind(this));
  22576. this.registerCustomAttribute('TestArrayOfInts', this.parseTestArrayOfInts.bind(this));
  22577. this.registerCustomAttribute('TestArrayOfEnums', this.parseTestArrayOfEnums.bind(this));
  22578. }
  22579. parseOperation(parser, result) {
  22580. if (result.op === 'test.conversion_func_op') {
  22581. parser.parseFunctionOp(result, false);
  22582. return true;
  22583. }
  22584. if (result.op === 'test.region_if') {
  22585. const unresolvedOperands = [];
  22586. while (parser.getToken().is(_.Token.percent_identifier)) {
  22587. unresolvedOperands.push(parser.parseOperand());
  22588. if (!parser.parseOptionalComma()) {
  22589. break;
  22590. }
  22591. }
  22592. parser.parseColon();
  22593. const inputTypes = parser.parseTypeList();
  22594. parser.resolveOperands(unresolvedOperands, inputTypes, result.operands);
  22595. parser.parseArrow();
  22596. const outputTypes = parser.parseFunctionResultTypes();
  22597. for (const t of outputTypes) {
  22598. result.addTypes([t]);
  22599. }
  22600. parser.parseKeyword('then');
  22601. const thenRegion = {};
  22602. parser.parseRegion(thenRegion);
  22603. result.regions.push(thenRegion);
  22604. parser.parseKeyword('else');
  22605. const elseRegion = {};
  22606. parser.parseRegion(elseRegion);
  22607. result.regions.push(elseRegion);
  22608. parser.parseKeyword('join');
  22609. const joinRegion = {};
  22610. parser.parseRegion(joinRegion);
  22611. result.regions.push(joinRegion);
  22612. return true;
  22613. }
  22614. if (result.op === 'test.affine_scope' || result.op === 'test.single_no_terminator_custom_asm_op') {
  22615. const region = result.addRegion();
  22616. parser.parseRegion(region);
  22617. return true;
  22618. }
  22619. if (result.op === 'test.with_nice_properties') {
  22620. result.compatibility = true;
  22621. let label = null;
  22622. if (parser.getToken().is(_.Token.string)) {
  22623. label = parser.getToken().getSpelling().str();
  22624. parser.consumeToken(_.Token.string);
  22625. } else {
  22626. label = parser.getToken().getSpelling().str();
  22627. parser.consumeToken(_.Token.bare_identifier);
  22628. }
  22629. parser.parseKeyword('is');
  22630. const negative = parser.consumeIf(_.Token.minus);
  22631. const value = parser.parseInteger();
  22632. result.addAttribute('prop', { label, value: negative ? -value : value });
  22633. parser.parseOptionalAttrDict(result.attributes);
  22634. return true;
  22635. }
  22636. // Test operation with default-valued properties and UnitProp
  22637. if (result.op === 'test.with_default_valued_properties') {
  22638. result.compatibility = true;
  22639. if (parser.parseOptionalKeyword('na')) {
  22640. // All defaults
  22641. } else {
  22642. const a = parser.parseInteger();
  22643. result.addAttribute('a', a);
  22644. if (parser.getToken().is(_.Token.string)) {
  22645. const __spelling = parser.getToken().getSpelling().str();
  22646. parser.consumeToken(_.Token.string);
  22647. result.addAttribute('b', __spelling);
  22648. }
  22649. if (parser.getToken().is(_.Token.integer) || parser.getToken().is(_.Token.minus)) {
  22650. const neg = parser.consumeIf(_.Token.minus);
  22651. const c = parser.parseInteger();
  22652. result.addAttribute('c', neg ? -c : c);
  22653. }
  22654. if (parser.consumeIf(_.Token.kw_unit)) {
  22655. result.addAttribute('unit', true);
  22656. } else if (parser.parseOptionalKeyword('unit_absent')) {
  22657. result.addAttribute('unit', false);
  22658. }
  22659. }
  22660. parser.parseOptionalAttrDict(result.attributes);
  22661. return true;
  22662. }
  22663. // Test operation with optional properties using some<...> syntax
  22664. if (result.op === 'test.with_optional_properties') {
  22665. result.compatibility = true;
  22666. const parseOptionalValue = () => {
  22667. if (parser.parseOptionalKeyword('some')) {
  22668. parser.parseLess();
  22669. let value = null;
  22670. if (parser.parseOptionalKeyword('none')) {
  22671. value = null;
  22672. } else if (parser.consumeIf(_.Token.kw_unit)) {
  22673. value = true;
  22674. } else if (parser.getToken().is(_.Token.string)) {
  22675. value = parser.getToken().getSpelling().str();
  22676. parser.consumeToken(_.Token.string);
  22677. } else {
  22678. const neg = parser.consumeIf(_.Token.minus);
  22679. value = parser.parseInteger();
  22680. if (neg) {
  22681. value = -value;
  22682. }
  22683. }
  22684. parser.parseGreater();
  22685. return { some: value };
  22686. }
  22687. if (parser.getToken().is(_.Token.string)) {
  22688. const __retval = parser.getToken().getSpelling().str();
  22689. parser.consumeToken(_.Token.string);
  22690. return __retval;
  22691. }
  22692. const neg = parser.consumeIf(_.Token.minus);
  22693. const value = parser.parseInteger();
  22694. return neg ? -value : value;
  22695. };
  22696. const knownAttrs = new Set(['anAttr', 'simple', 'simplei8', 'simpleui8', 'nonTrivialStorage', 'hasDefault', 'nested', 'longSyntax', 'hasUnit', 'maybeUnit']);
  22697. while (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() !== 'loc') {
  22698. const tokenValue = parser.getTokenSpelling().str();
  22699. // Stop if this looks like an operation name (not a known attribute)
  22700. if (!knownAttrs.has(tokenValue)) {
  22701. break;
  22702. }
  22703. const name = parser.getToken().getSpelling().str();
  22704. parser.consumeToken(_.Token.bare_identifier);
  22705. if (name === 'hasUnit') {
  22706. result.addAttribute(name, true);
  22707. } else if (parser.parseOptionalEqual()) {
  22708. result.addAttribute(name, parseOptionalValue());
  22709. } else {
  22710. break;
  22711. }
  22712. }
  22713. parser.parseOptionalAttrDict(result.attributes);
  22714. return true;
  22715. }
  22716. if (result.op === 'test.wrapping_region') {
  22717. parser.parseKeyword('wraps');
  22718. const region = result.addRegion();
  22719. const block = { operations: [] };
  22720. region.blocks = [block];
  22721. const wrappedOp = parser.parseGenericOperation();
  22722. block.operations.push(wrappedOp);
  22723. if (wrappedOp.results) {
  22724. for (const opResult of wrappedOp.results) {
  22725. result.addTypes([opResult.type]);
  22726. }
  22727. }
  22728. return true;
  22729. }
  22730. if (result.op === 'test.pretty_printed_region') {
  22731. result.operands = parser.parseOperandList();
  22732. if (parser.parseOptionalKeyword('start')) {
  22733. const innerOpName = parser.parseCustomOperationName();
  22734. result.addAttribute('inner_op', innerOpName);
  22735. parser.parseKeyword('end');
  22736. parser.parseColon();
  22737. const fnType = parser.parseFunctionType();
  22738. if (fnType && fnType.inputs) {
  22739. parser.resolveOperands(result.operands, fnType.inputs);
  22740. }
  22741. if (fnType && fnType.results) {
  22742. for (let i = 0; i < fnType.results.length; i++) {
  22743. result.addTypes([fnType.results[i]]);
  22744. }
  22745. }
  22746. parser.parseOptionalLocationSpecifier();
  22747. } else {
  22748. parser.parseLParen();
  22749. const region = result.addRegion();
  22750. parser.parseRegion(region);
  22751. parser.parseRParen();
  22752. parser.parseColon();
  22753. const fnType = parser.parseFunctionType();
  22754. if (fnType && fnType.inputs) {
  22755. parser.resolveOperands(result.operands, fnType.inputs);
  22756. }
  22757. if (fnType && fnType.results) {
  22758. for (let i = 0; i < fnType.results.length; i++) {
  22759. result.addTypes([fnType.results[i]]);
  22760. }
  22761. }
  22762. }
  22763. return true;
  22764. }
  22765. if (result.op === 'test.isolated_region') {
  22766. const operand = parser.parseOperand();
  22767. const indexType = new _.IndexType();
  22768. parser.resolveOperand(operand, indexType, result.operands);
  22769. const region = result.addRegion();
  22770. parser.parseRegion(region, [{ value: operand.toString(), type: new _.IndexType() }]);
  22771. return true;
  22772. }
  22773. if (result.op === 'test.string_attr_pretty_name') {
  22774. const numResults = parser.getNumResults();
  22775. for (let i = 0; i < numResults; i++) {
  22776. result.addTypes([new _.IntegerType('i32')]);
  22777. }
  22778. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  22779. if (!result.attributes.has('names') && numResults > 0) {
  22780. const names = [];
  22781. for (let i = 0; i < numResults; i++) {
  22782. const resultName = parser.getResultName(i);
  22783. // Only use names that don't start with a digit (ref impl line 572)
  22784. if (resultName && resultName.length > 0 && !/^\d/.test(resultName)) {
  22785. names.push(new _.StringAttr(resultName));
  22786. } else {
  22787. names.push(new _.StringAttr(''));
  22788. }
  22789. }
  22790. result.attributes.set('names', new _.ArrayAttr(names));
  22791. }
  22792. return true;
  22793. }
  22794. if (result.op === 'test.with_bounds_region') {
  22795. parser.parseOptionalAttrDict(result.attributes);
  22796. const argName = parser.parseOperand();
  22797. parser.parseColon();
  22798. const argType = parser.parseType();
  22799. const region = result.addRegion();
  22800. const arg = { value: argName, type: argType };
  22801. parser.parseRegion(region, [arg]);
  22802. return true;
  22803. }
  22804. return super.parseOperation(parser, result);
  22805. }
  22806. parseTestBitEnumProp(parser, type) {
  22807. if (type.values.includes(parser.getTokenSpelling().str())) {
  22808. return this.parseEnumFlags(parser, type, ',');
  22809. }
  22810. return null;
  22811. }
  22812. parseTestEnumAttr(parser, type) {
  22813. const token = parser.getToken();
  22814. const spelling = token.getSpelling().str();
  22815. if (token && type.values && type.values.includes(spelling)) {
  22816. parser.consumeToken();
  22817. return new _.TypedAttr(spelling, null);
  22818. }
  22819. return null;
  22820. }
  22821. parseTestEnumPropAttrForm(parser) {
  22822. return parser.parseOptionalAttribute();
  22823. }
  22824. parseTestBitEnumPropNamed(parser) {
  22825. if (parser.parseOptionalKeyword('bit_enum')) {
  22826. if (parser.parseOptionalLess()) {
  22827. const flags = [];
  22828. while (parser.getToken().isNot(_.Token.greater)) {
  22829. const value = parser.getToken().getSpelling().str();
  22830. parser.consumeToken(_.Token.bare_identifier);
  22831. flags.push(value);
  22832. parser.parseOptionalComma();
  22833. }
  22834. parser.parseGreater();
  22835. return new _.TypedAttr(`bit_enum<${flags.join(', ')}>`, null);
  22836. }
  22837. }
  22838. return null;
  22839. }
  22840. // Parse CompoundNestedOuterType: assemblyFormat = "`<` `i` $inner `>`"
  22841. // Full form: !test.cmpnd_nested_outer<i !test.cmpnd_inner<...>>
  22842. // Elided form: <i <...>>
  22843. parseCompoundNestedOuterType(parser) {
  22844. parser.parseLess();
  22845. parser.parseKeyword('i');
  22846. // Parse $inner - could be full (!test.cmpnd_inner<...>) or elided (<...>)
  22847. const inner = parser.getToken().is(_.Token.exclamation_identifier) ? parser.parseType() : this.parseCompoundNestedInnerType(parser);
  22848. parser.parseGreater();
  22849. return new _.Type(`!test.cmpnd_nested_outer<i ${inner}>`);
  22850. }
  22851. // Parse CompoundNestedInnerType: assemblyFormat = "`<` $some_int $cmpdA `>`"
  22852. // Full form: !test.cmpnd_inner<42 !test.cmpnd_a<...>>
  22853. // Elided form: <42 <...>>
  22854. parseCompoundNestedInnerType(parser) {
  22855. parser.parseLess();
  22856. const someInt = parser.parseInteger();
  22857. // Parse $cmpdA - could be full (!test.cmpnd_a<...>) or elided (<...>)
  22858. const cmpdA = parser.getToken().is(_.Token.exclamation_identifier) ? parser.parseType() : this.parseCompoundTypeA(parser);
  22859. parser.parseGreater();
  22860. return new _.Type(`!test.cmpnd_inner<${someInt} ${cmpdA}>`);
  22861. }
  22862. // Parse CompoundTypeA: hasCustomAssemblyFormat = 1
  22863. // Example: <1, !test.smpla, [5, 6]>
  22864. parseCompoundTypeA(parser) {
  22865. parser.parseLess();
  22866. const width = parser.parseInteger();
  22867. parser.parseComma();
  22868. const oneType = parser.parseType();
  22869. parser.parseComma();
  22870. parser.parseLSquare();
  22871. const arrayOfInts = [];
  22872. while (parser.getToken().isNot(_.Token.r_square)) {
  22873. arrayOfInts.push(parser.parseInteger());
  22874. parser.parseOptionalComma();
  22875. }
  22876. parser.parseRSquare();
  22877. parser.parseGreater();
  22878. return new _.Type(`!test.cmpnd_a<${width}, ${oneType}, [${arrayOfInts.join(', ')}]>`);
  22879. }
  22880. parseOptionalLoc(parser, op, attrName = 'loc') {
  22881. const loc = parser.parseOptionalLocationSpecifier();
  22882. if (loc) {
  22883. op.addAttribute(attrName, loc);
  22884. } else {
  22885. op.addAttribute(attrName, parser.location());
  22886. }
  22887. }
  22888. parseDummyRegionRef() {
  22889. }
  22890. parseDummySuccessorRef() {
  22891. }
  22892. parseTestAttrUgly(parser) {
  22893. parser.parseKeyword('begin');
  22894. const attr = parser.parseAttribute();
  22895. parser.parseKeyword('end');
  22896. return attr;
  22897. }
  22898. // Parse TestArrayOfUglyAttrs: assemblyFormat = "`[` (`]`) : ($value^ ` ` `]`)?"
  22899. parseTestArrayOfUglyAttrs(parser) {
  22900. parser.parseLSquare();
  22901. const elements = [];
  22902. parser.parseCommaSeparatedListUntil(_.Token.r_square, () => {
  22903. elements.push(this.parseTestAttrUgly(parser));
  22904. });
  22905. return new _.ArrayAttr(elements);
  22906. }
  22907. // Parse TestArrayOfInts: assemblyFormat = "`[` (`]`) : ($value^ `]`)?"
  22908. parseTestArrayOfInts(parser) {
  22909. parser.parseLSquare();
  22910. const elements = [];
  22911. parser.parseCommaSeparatedListUntil(_.Token.r_square, () => {
  22912. const isNegative = parser.consumeIf(_.Token.minus);
  22913. const value = parser.parseInteger();
  22914. elements.push(new _.IntegerAttr(null, isNegative ? -value : value));
  22915. });
  22916. return new _.ArrayAttr(elements);
  22917. }
  22918. // Parse TestArrayOfEnums: elements are SimpleEnumAttr values (a, b, etc.)
  22919. parseTestArrayOfEnums(parser) {
  22920. parser.parseLSquare();
  22921. const elements = [];
  22922. parser.parseCommaSeparatedListUntil(_.Token.r_square, () => {
  22923. if (parser.getToken().is(_.Token.string)) {
  22924. elements.push(new _.TypedAttr(parser.parseString(), null));
  22925. } else {
  22926. const value = parser.parseKeyword();
  22927. elements.push(new _.TypedAttr(value, null));
  22928. }
  22929. });
  22930. return new _.ArrayAttr(elements);
  22931. }
  22932. parseOptionalCustomParser(parser, op, attrName = 'attr') {
  22933. if (!parser.parseOptionalKeyword('foo')) {
  22934. return null; // Optional group not taken
  22935. }
  22936. const attr = parser.parseAttribute();
  22937. op.addAttribute(attrName, attr.value);
  22938. return true;
  22939. }
  22940. parseDimensionList(parser, op, attrName = 'dimension_list') {
  22941. const dims = [];
  22942. if (parser.parseOptionalLSquare()) {
  22943. parser.parseOptionalRSquare();
  22944. op.addAttribute(attrName, []);
  22945. return;
  22946. }
  22947. for (;;) {
  22948. if (parser.consumeIf(_.Token.question)) {
  22949. dims.push(-1);
  22950. } else if (parser.getToken().is(_.Token.integer)) {
  22951. dims.push(parser.parseInteger());
  22952. } else {
  22953. break;
  22954. }
  22955. const token = parser.getToken();
  22956. const spelling = token.getSpelling().str();
  22957. if (token && token.kind === _.Token.bare_identifier && spelling.startsWith('x')) {
  22958. const rest = spelling.slice(1);
  22959. if (rest === '') {
  22960. parser.consumeToken();
  22961. } else if (/^\d+$/.test(rest)) {
  22962. parser.consumeToken();
  22963. dims.push(parseInt(rest, 10));
  22964. } else if (rest === '?') {
  22965. parser.consumeToken();
  22966. dims.push(-1);
  22967. } else {
  22968. break;
  22969. }
  22970. } else {
  22971. break;
  22972. }
  22973. }
  22974. op.addAttribute(attrName, dims);
  22975. }
  22976. parseCustomOptionalOperand(parser, result) {
  22977. if (parser.parseOptionalLParen()) {
  22978. const unresolvedOperand = parser.parseOperand();
  22979. parser.resolveOperand(unresolvedOperand, null, result.operands);
  22980. parser.parseRParen();
  22981. }
  22982. }
  22983. // Custom directive: operand [, optOperand] -> (varOperands)
  22984. parseCustomDirectiveOperands(parser, result) {
  22985. const unresolvedRequired = parser.parseOperand();
  22986. parser.resolveOperand(unresolvedRequired, null, result.operands);
  22987. if (parser.parseOptionalComma()) {
  22988. const unresolvedOptional = parser.parseOperand();
  22989. parser.resolveOperand(unresolvedOptional, null, result.operands);
  22990. }
  22991. parser.parseArrow();
  22992. parser.parseLParen();
  22993. while (parser.getToken().is(_.Token.percent_identifier)) {
  22994. const unresolvedVar = parser.parseOperand();
  22995. parser.resolveOperand(unresolvedVar, null, result.operands);
  22996. if (!parser.parseOptionalComma()) {
  22997. break;
  22998. }
  22999. }
  23000. parser.parseRParen();
  23001. }
  23002. // Custom directive: operands and types together
  23003. parseCustomDirectiveOperandsAndTypes(parser, result) {
  23004. this.parseCustomDirectiveOperands(parser, result);
  23005. this.parseCustomDirectiveResults(parser, result);
  23006. }
  23007. // Custom directive: : type [, optType] -> (varTypes)
  23008. parseCustomDirectiveResults(parser, result) {
  23009. parser.parseColon();
  23010. const type = parser.parseType();
  23011. if (result.operands.length > 0) {
  23012. result.operands[0].type = type;
  23013. }
  23014. if (parser.parseOptionalComma()) {
  23015. const optType = parser.parseType();
  23016. if (result.operands.length > 1) {
  23017. result.operands[1].type = optType;
  23018. }
  23019. }
  23020. parser.parseArrow();
  23021. parser.parseLParen();
  23022. let idx = 2; // Start after first two operands
  23023. while (parser.getToken().isNot(_.Token.r_paren)) {
  23024. const varType = parser.parseType();
  23025. if (result.operands.length > idx) {
  23026. result.operands[idx].type = varType;
  23027. }
  23028. idx++;
  23029. if (!parser.parseOptionalComma()) {
  23030. break;
  23031. }
  23032. }
  23033. parser.parseRParen();
  23034. }
  23035. parseCustomDirectiveWithTypeRefs(parser, result) {
  23036. // Parses: type_refs_capture : type [, type] -> (types)
  23037. parser.parseKeyword('type_refs_capture');
  23038. this.parseCustomDirectiveResults(parser, result);
  23039. }
  23040. parseCustomDirectiveRegions(parser, result) {
  23041. const region = result.addRegion();
  23042. parser.parseRegion(region);
  23043. while (parser.parseOptionalComma()) {
  23044. const varRegion = result.addRegion();
  23045. parser.parseRegion(varRegion);
  23046. }
  23047. }
  23048. parseCustomDirectiveSuccessors(parser, result) {
  23049. if (!result.successors) {
  23050. result.successors = [];
  23051. }
  23052. const successor = {};
  23053. successor.label = parser.getToken().getSpelling().str();
  23054. parser.consumeToken(_.Token.caret_identifier);
  23055. result.successors.push(successor);
  23056. while (parser.parseOptionalComma()) {
  23057. const varSuccessor = {};
  23058. varSuccessor.label = parser.getToken().getSpelling().str();
  23059. parser.consumeToken(_.Token.caret_identifier);
  23060. result.successors.push(varSuccessor);
  23061. }
  23062. }
  23063. parseCustomDirectiveAttrDict(parser, result) {
  23064. if (parser.getToken().is(_.Token.l_brace)) {
  23065. parser.parseAttributeDict(result.attributes);
  23066. }
  23067. }
  23068. parseCustomDirectiveAttributes(parser, result) {
  23069. const attr = parser.parseAttribute();
  23070. result.addAttribute('attr', attr);
  23071. if (parser.parseOptionalComma()) {
  23072. const optAttr = parser.parseAttribute();
  23073. result.addAttribute('optAttr', optAttr);
  23074. }
  23075. }
  23076. parseCustomDirectiveSpacing(parser, op, attrName) {
  23077. if (attrName) {
  23078. const name = attrName.name || attrName;
  23079. const attr = parser.parseAttribute();
  23080. op.addAttribute(name, attr);
  23081. }
  23082. }
  23083. parseCustomDirectiveOptionalOperandRef(parser) {
  23084. parser.parseInteger();
  23085. }
  23086. parseSwitchCases(parser, result) {
  23087. const caseValues = [];
  23088. while (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === 'case') {
  23089. parser.parseKeyword('case');
  23090. const value = parser.parseInteger();
  23091. caseValues.push(value);
  23092. const region = result.addRegion();
  23093. parser.parseRegion(region);
  23094. }
  23095. result.addAttribute('cases', `array<i64: ${caseValues.join(', ')}>`);
  23096. }
  23097. parseUsingPropertyInCustom(parser, op, propArg) {
  23098. const values = [];
  23099. parser.parseLSquare();
  23100. while (parser.getToken().isNot(_.Token.r_square)) {
  23101. const value = parser.parseInteger();
  23102. values.push(value);
  23103. if (!parser.parseOptionalComma()) {
  23104. break;
  23105. }
  23106. }
  23107. parser.parseRSquare();
  23108. if (propArg) {
  23109. const propName = typeof propArg === 'string' ? propArg : propArg.name;
  23110. op.addAttribute(propName, `array<i64: ${values.join(', ')}>`);
  23111. }
  23112. }
  23113. parseIntProperty(parser, op, propArg) {
  23114. const value = parser.parseInteger();
  23115. if (propArg) {
  23116. const propName = typeof propArg === 'string' ? propArg : propArg.name;
  23117. op.addAttribute(propName, value);
  23118. }
  23119. }
  23120. parseSumProperty(parser, op, propArg) {
  23121. const second = parser.parseInteger();
  23122. parser.parseEqual();
  23123. parser.parseInteger(); // sum value (validation skipped)
  23124. if (propArg) {
  23125. const propName = typeof propArg === 'string' ? propArg : propArg.name;
  23126. op.addAttribute(propName, second);
  23127. }
  23128. }
  23129. inferResultTypes(op, vars) {
  23130. if (op.op === 'test.format_infer_type' || op.op === 'test.format_infer_type2') {
  23131. op.addTypes([new _.IntegerType('i16')]);
  23132. return;
  23133. }
  23134. if (op.op === 'test.format_types_match_attr') {
  23135. const valueAttr = op.attributes.get('value');
  23136. if (valueAttr && valueAttr.type) {
  23137. op.addTypes([valueAttr.type]);
  23138. return;
  23139. }
  23140. }
  23141. if (op.op === 'test.format_infer_type_all_operands_and_types' ||
  23142. op.op === 'test.format_infer_type_all_types_one_operand' ||
  23143. op.op === 'test.format_infer_type_all_types_two_operands' ||
  23144. op.op === 'test.format_infer_type_all_types' ||
  23145. op.op === 'test.format_infer_type_variadic_operands') {
  23146. for (const operand of op.operands) {
  23147. if (operand.type) {
  23148. op.addTypes([operand.type]);
  23149. }
  23150. }
  23151. return;
  23152. }
  23153. if (op.op === 'test.format_infer_type_regions') {
  23154. const region = op.regions[0];
  23155. const block = region?.blocks?.[0];
  23156. if (block?.arguments) {
  23157. for (const arg of block.arguments) {
  23158. if (arg.type) {
  23159. op.addTypes([arg.type]);
  23160. }
  23161. }
  23162. }
  23163. return;
  23164. }
  23165. if (op.op === 'test.with_properties_and_inferred_type') {
  23166. const lhsAttr = op.attributes.get('lhs');
  23167. const rhsAttr = op.getAttr('rhs');
  23168. const lhs = lhsAttr && lhsAttr.value !== undefined ? lhsAttr.value : (lhsAttr || 0);
  23169. const rhs = rhsAttr !== undefined && rhsAttr !== null ? rhsAttr : 0;
  23170. const width = (typeof lhs === 'number' ? lhs : 0) + (typeof rhs === 'number' ? rhs : 0);
  23171. op.addTypes([new _.IntegerType(`i${width}`)]);
  23172. return;
  23173. }
  23174. super.inferResultTypes(op, vars);
  23175. }
  23176. declareResource(key) {
  23177. if (!this.blobManager.has(key)) {
  23178. this.blobManager.set(key, new _.DenseResourceElementsHandle(key));
  23179. }
  23180. return this.blobManager.get(key);
  23181. }
  23182. getResourceKey(handle) {
  23183. return handle.key;
  23184. }
  23185. parseResource(entry) {
  23186. const blob = entry.parseAsBlob();
  23187. this.blobManager.get(entry.key).blob = blob;
  23188. }
  23189. };
  23190. _.triton = {};
  23191. _.triton.PointerType = class extends _.Type {
  23192. constructor(pointeeType, addressSpace) {
  23193. super(null);
  23194. this.pointeeType = pointeeType;
  23195. this.addressSpace = addressSpace || 1;
  23196. }
  23197. static parse(parser) {
  23198. parser.parseLess();
  23199. const pointeeType = parser.parseType();
  23200. let addressSpace = 1;
  23201. if (parser.parseOptionalComma()) {
  23202. addressSpace = parseInt(parser.getToken().getSpelling().str(), 10);
  23203. parser.consumeToken(_.Token.integer);
  23204. }
  23205. parser.parseGreater();
  23206. return new _.triton.PointerType(pointeeType, addressSpace);
  23207. }
  23208. toString() {
  23209. const pointeeStr = this.pointeeType?.toString ? this.pointeeType.toString() : this.pointeeType;
  23210. if (this.addressSpace && this.addressSpace !== 1) {
  23211. return `!tt.ptr<${pointeeStr}, ${this.addressSpace}>`;
  23212. }
  23213. return `!tt.ptr<${pointeeStr}>`;
  23214. }
  23215. };
  23216. _.triton.TritonDialect = class extends _.Dialect {
  23217. constructor(operations) {
  23218. super(operations, 'tt');
  23219. this.registerCustomType('TT_Ptr', (parser) => _.triton.PointerType.parse(parser));
  23220. this.registerCustomType('TT_TensorDescType', this.parseTensorDescType.bind(this));
  23221. this.registerCustomType('TT_TensorPtr', (parser) => _.triton.PointerType.parse(parser));
  23222. }
  23223. parseType(parser, dialect) {
  23224. const typeName = parser.parseOptionalKeyword();
  23225. if (!typeName) {
  23226. return null;
  23227. }
  23228. // Handle ptr type specifically to properly parse pointee type
  23229. if (typeName === 'ptr' && parser.getToken().is(_.Token.less)) {
  23230. return _.triton.PointerType.parse(parser);
  23231. }
  23232. let type = `!${dialect}.${typeName}`;
  23233. if (parser.getToken().is(_.Token.less)) {
  23234. const content = parser.skip('<');
  23235. type += content;
  23236. }
  23237. return new _.Type(type);
  23238. }
  23239. parseOperation(parser, result) {
  23240. if (result.op === 'tt.func') {
  23241. parser.parseFunctionOp(result, false);
  23242. return true;
  23243. }
  23244. return super.parseOperation(parser, result);
  23245. }
  23246. parseTensorDescType(parser) {
  23247. if (parser.getToken().is(_.Token.less)) {
  23248. const content = parser.skip('<');
  23249. return new _.Type(`!tt.tensor_desc${content}`);
  23250. }
  23251. return null;
  23252. }
  23253. inferResultTypes(op, vars) {
  23254. if (op.op === 'tt.load' && op.operands.length > 0) {
  23255. const ptrType = op.operands[0].type;
  23256. if (ptrType instanceof _.triton.PointerType) {
  23257. op.addTypes([ptrType.pointeeType]);
  23258. } else if (ptrType instanceof _.RankedTensorType) {
  23259. const elementType = ptrType.elementType;
  23260. if (elementType instanceof _.triton.PointerType) {
  23261. const pointeeType = elementType.pointeeType;
  23262. op.addTypes([new _.RankedTensorType(ptrType.shape, pointeeType, ptrType.encoding)]);
  23263. return;
  23264. }
  23265. }
  23266. }
  23267. if (op.op === 'tt.unsplat') {
  23268. const srcType = op.operands[0]?.type;
  23269. if (srcType instanceof _.RankedTensorType) {
  23270. op.addTypes([srcType.elementType]);
  23271. return;
  23272. }
  23273. }
  23274. super.inferResultTypes(op, vars);
  23275. }
  23276. };
  23277. _.triton.gpu = {};
  23278. _.triton.gpu.TritonGPUDialect = class extends _.Dialect {
  23279. constructor(operations) {
  23280. super(operations, 'ttg');
  23281. this.registerCustomType('TTG_MemDescType', this.parseMemDescType.bind(this));
  23282. }
  23283. parseOperation(parser, result) {
  23284. if (result.op === 'ttg.warp_specialize') {
  23285. const unresolvedOperands = [];
  23286. parser.parseLParen();
  23287. while (parser.getToken().isNot(_.Token.r_paren)) {
  23288. unresolvedOperands.push(parser.parseOperand());
  23289. if (parser.getToken().isNot(_.Token.r_paren)) {
  23290. parser.parseComma();
  23291. }
  23292. }
  23293. parser.parseRParen();
  23294. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  23295. parser.parseKeyword('default');
  23296. const defaultRegion = {};
  23297. parser.parseRegion(defaultRegion);
  23298. result.regions.push(defaultRegion);
  23299. const partitionNumWarps = [];
  23300. let partitionIndex = 0;
  23301. while (parser.getToken().is(_.Token.bare_identifier) && parser.getTokenSpelling().str() === `partition${partitionIndex}`) {
  23302. parser.consumeToken(_.Token.bare_identifier);
  23303. const argResult = parser.parseFunctionArgumentList();
  23304. parser.parseKeyword('num_warps');
  23305. parser.parseLParen();
  23306. const numWarps = parser.getToken().getSpelling().str();
  23307. parser.consumeToken();
  23308. partitionNumWarps.push(parseInt(numWarps, 10));
  23309. parser.parseRParen();
  23310. const partitionRegion = {};
  23311. partitionRegion.arguments = argResult.arguments;
  23312. parser.parseRegion(partitionRegion);
  23313. if (!result.regions[1]) {
  23314. result.regions[1] = { blocks: [{ operations: [] }] };
  23315. }
  23316. partitionIndex++;
  23317. }
  23318. parser.parseColon();
  23319. const fnType = parser.parseType();
  23320. if (fnType instanceof _.FunctionType) {
  23321. result.addAttribute('function_type', new _.TypeAttrOf(fnType));
  23322. parser.resolveOperands(unresolvedOperands, fnType.inputs, result.operands);
  23323. result.addTypes(fnType.results);
  23324. } else {
  23325. result.addAttribute('function_type', new _.TypeAttrOf(new _.FunctionType([], [fnType])));
  23326. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  23327. result.addTypes([fnType]);
  23328. }
  23329. if (partitionNumWarps.length > 0) {
  23330. result.addAttribute('partitionNumWarps', { type: 'array', element_type: 'i32', value: partitionNumWarps });
  23331. }
  23332. return true;
  23333. }
  23334. if (result.op === 'ttg.barrier') {
  23335. const flags = [];
  23336. flags.push(parser.getToken().getSpelling().str());
  23337. parser.consumeToken(_.Token.bare_identifier);
  23338. while (parser.parseOptionalVerticalBar()) {
  23339. flags.push(parser.getToken().getSpelling().str());
  23340. parser.consumeToken(_.Token.bare_identifier);
  23341. }
  23342. result.addAttribute('addrSpace', new _.TypedAttr(flags.join('|')));
  23343. return true;
  23344. }
  23345. return super.parseOperation(parser, result);
  23346. }
  23347. parseType(parser, dialect) {
  23348. const typeName = parser.parseOptionalKeyword();
  23349. if (!typeName) {
  23350. return null;
  23351. }
  23352. let type = `!${dialect}.${typeName}`;
  23353. if (parser.getToken().is(_.Token.less)) {
  23354. const content = parser.skip('<');
  23355. type += content;
  23356. }
  23357. return new _.Type(type);
  23358. }
  23359. parseMemDescType(parser) {
  23360. // Handle shorthand MemDescType notation: <dims x elementType, attributes...>
  23361. // Full notation would be: !ttg.memdesc<dims x elementType, attributes...>
  23362. if (parser.getToken().isNot(_.Token.less)) {
  23363. return null;
  23364. }
  23365. const content = parser.skip('<');
  23366. return new _.Type(`!ttg.memdesc<${content}>`);
  23367. }
  23368. };
  23369. _.GluonDialect = class extends _.Dialect {
  23370. constructor(operations) {
  23371. super(operations, 'gluon');
  23372. }
  23373. };
  23374. _.TritonNvidiaGPUDialect = class extends _.Dialect {
  23375. constructor(operations) {
  23376. super(operations, 'ttng');
  23377. this.registerCustomDirective('Token', this.parseToken.bind(this));
  23378. this.registerCustomDirective('BarriersAndPreds', this.parseBarriersAndPreds.bind(this));
  23379. }
  23380. parseToken(parser, op, depOperands, tokenTypeArr) {
  23381. // custom<Token>($acc_dep, type($token))
  23382. // depOperands = operands array, tokenTypeArr = types array
  23383. if (!parser.parseOptionalLSquare()) {
  23384. return;
  23385. }
  23386. // Push token type to the types array
  23387. if (Array.isArray(tokenTypeArr)) {
  23388. tokenTypeArr.push(new _.Type('!ttng.async.token'));
  23389. }
  23390. if (parser.getToken().is(_.Token.r_square)) {
  23391. parser.parseRSquare();
  23392. return;
  23393. }
  23394. if (parser.getToken().is(_.Token.percent_identifier)) {
  23395. const dep = parser.parseOperand();
  23396. if (!Array.isArray(depOperands)) {
  23397. throw new mlir.Error(`Expected depOperands to be an array ${parser.location()}`);
  23398. }
  23399. depOperands.push(dep);
  23400. }
  23401. parser.parseRSquare();
  23402. }
  23403. parseBarriersAndPreds(parser, op, barrierOperands, predOperands) {
  23404. while (parser.parseOptionalComma()) {
  23405. if (parser.getToken().is(_.Token.percent_identifier)) {
  23406. const barrier = parser.parseOperand();
  23407. if (!Array.isArray(barrierOperands)) {
  23408. throw new mlir.Error(`Expected barrierOperands to be an array ${parser.location()}`);
  23409. }
  23410. barrierOperands.push(barrier);
  23411. if (parser.parseOptionalLSquare()) {
  23412. if (parser.getToken().is(_.Token.percent_identifier)) {
  23413. const pred = parser.parseOperand();
  23414. if (!Array.isArray(predOperands)) {
  23415. throw new mlir.Error(`Expected predOperands to be an array ${parser.location()}`);
  23416. }
  23417. predOperands.push(pred);
  23418. }
  23419. parser.parseRSquare();
  23420. }
  23421. }
  23422. }
  23423. }
  23424. parseType(parser, dialect) {
  23425. const mnemonic = parser.parseOptionalKeyword();
  23426. if (mnemonic) {
  23427. let type = `!${dialect}.${mnemonic}`;
  23428. if (parser.getToken().is(_.Token.less)) {
  23429. const content = parser.skip('<');
  23430. type += content;
  23431. }
  23432. return new _.Type(type);
  23433. }
  23434. return null;
  23435. }
  23436. };
  23437. _.TritonAMDGPUDialect = class extends _.Dialect {
  23438. constructor(operations) {
  23439. super(operations, 'amdg');
  23440. this.registerCustomType('TT_Ptr', 'tt.ptr');
  23441. this.registerCustomType('TT_TensorPtr', 'tt.ptr');
  23442. this.registerCustomType('TTG_MemDescType', 'ttg.memdesc');
  23443. }
  23444. parseType(parser, dialect) {
  23445. const typeName = parser.parseOptionalKeyword();
  23446. if (!typeName) {
  23447. return null;
  23448. }
  23449. let type = `!${dialect}.${typeName}`;
  23450. if (parser.getToken().is(_.Token.less)) {
  23451. const content = parser.skip('<');
  23452. type += content;
  23453. }
  23454. return new _.Type(type);
  23455. }
  23456. };
  23457. _.ProtonDialect = class extends _.Dialect {
  23458. constructor(operations) {
  23459. super(operations, 'proton');
  23460. }
  23461. };
  23462. _.MichelsonDialect = class extends _.Dialect {
  23463. constructor(operations) {
  23464. super(operations, 'michelson');
  23465. }
  23466. parseType(parser, dialect) {
  23467. const typeName = parser.parseOptionalKeyword();
  23468. if (!typeName) {
  23469. return null;
  23470. }
  23471. let type = `!${dialect}.${typeName}`;
  23472. if ((typeName === 'big' || typeName === 'chain' || typeName === 'key') && parser.getToken().is('_')) {
  23473. parser.consumeToken('_');
  23474. const suffix = parser.getToken().getSpelling().str();
  23475. parser.consumeToken(_.Token.bare_identifier);
  23476. type += `_${suffix}`;
  23477. }
  23478. const simpleTypes = ['int', 'bytes', 'operation', 'nat', 'string', 'unit', 'bool', 'mutez', 'timestamp', 'address', 'key', 'signature', 'chain_id', 'key_hash'];
  23479. if (simpleTypes.includes(type.substring(11))) { // Remove "!michelson." prefix
  23480. return new _.Type(type);
  23481. }
  23482. const typesWithParams = ['pair', 'list', 'option', 'or', 'map', 'big_map', 'set', 'contract', 'lambda'];
  23483. if (typesWithParams.includes(type.substring(11))) {
  23484. if (parser.getToken().is(_.Token.less)) {
  23485. const content = parser.skip('<');
  23486. type += content;
  23487. }
  23488. return new _.Type(type);
  23489. }
  23490. return null;
  23491. }
  23492. };
  23493. _.PlanDialect = class extends _.Dialect {
  23494. constructor(operations) {
  23495. super(operations, 'plan');
  23496. this.registerCustomDirective('WithValuesTypes', this.parseWithValuesTypes.bind(this));
  23497. }
  23498. parseWithValuesTypes(parser, op, elementsRef, resultTypes, elementsTypes) {
  23499. const resultType = parser.parseType();
  23500. resultTypes.push(resultType);
  23501. if (op.types.length === 0) {
  23502. op.addTypes([resultType]);
  23503. } else {
  23504. op.types[0] = resultType;
  23505. }
  23506. // Derive element types from tensor's element type (matching C++ getElementTypeOrSelf)
  23507. const elementType = resultType.elementType || resultType;
  23508. // Populate element types for each element operand
  23509. if (elementsRef && elementsRef.length > 0) {
  23510. for (let i = 0; i < elementsRef.length; i++) {
  23511. elementsTypes.push(elementType);
  23512. }
  23513. }
  23514. }
  23515. };
  23516. _.KernelDialect = class extends _.Dialect {
  23517. constructor(operations) {
  23518. super(operations, 'kernel');
  23519. this.registerCustomDirective('KernelFunctionalType', this.parseKernelFunctionalType.bind(this));
  23520. }
  23521. parseKernelFunctionalType(parser, op /*, args */) {
  23522. parser.parseLParen();
  23523. if (parser.getToken().isNot(_.Token.r_paren)) {
  23524. do {
  23525. parser.parseType();
  23526. } while (parser.parseOptionalComma());
  23527. }
  23528. parser.parseRParen();
  23529. parser.parseArrow();
  23530. const resultTypes = [];
  23531. if (parser.parseOptionalLParen()) {
  23532. if (parser.getToken().isNot(_.Token.r_paren)) {
  23533. do {
  23534. resultTypes.push(parser.parseType());
  23535. } while (parser.parseOptionalComma());
  23536. }
  23537. parser.parseRParen();
  23538. } else {
  23539. resultTypes.push(parser.parseType());
  23540. }
  23541. if (resultTypes.length > 0) {
  23542. op.addTypes(resultTypes);
  23543. }
  23544. }
  23545. inferResultTypes(op, vars) {
  23546. // kernel.combiner: result types are the first half of the input types
  23547. if (op.op === 'kernel.combiner') {
  23548. const inputsEntry = vars.get('inputs');
  23549. if (inputsEntry?.types?.length > 0) {
  23550. const numPairs = Math.floor(inputsEntry.types.length / 2);
  23551. const resultTypes = inputsEntry.types.slice(0, numPairs);
  23552. op.addTypes(resultTypes);
  23553. return;
  23554. }
  23555. }
  23556. super.inferResultTypes(op, vars);
  23557. }
  23558. };
  23559. _.TensorRTDialect = class extends _.Dialect {
  23560. constructor(operations) {
  23561. super(operations, 'tensorrt');
  23562. this.registerCustomAttribute('TensorRT_TopKOperationAttr', this.parseEnumAttrBracket.bind(this));
  23563. this.registerCustomAttribute('TensorRT_ScatterModeAttr', this.parseEnumAttrBracket.bind(this));
  23564. this.registerCustomAttribute('TensorRT_ResizeSelectorAttr', this.parseEnumAttrBracket.bind(this));
  23565. this.registerCustomAttribute('TensorRT_ResizeRoundModeAttr', this.parseEnumAttrBracket.bind(this));
  23566. this.registerCustomAttribute('TensorRT_ResizeModeAttr', this.parseEnumAttrBracket.bind(this));
  23567. this.registerCustomAttribute('TensorRT_ResizeCoordinateTransformationAttr', this.parseEnumAttrBracket.bind(this));
  23568. this.registerCustomAttribute('TensorRT_ReduceOperationAttr', this.parseEnumAttrBracket.bind(this));
  23569. this.registerCustomAttribute('TensorRT_PaddingModeAttr', this.parseEnumAttrBracket.bind(this));
  23570. this.registerCustomAttribute('TensorRT_MatrixOperationAttr', this.parseEnumAttrBracket.bind(this));
  23571. this.registerCustomAttribute('TensorRT_LoopOutputAttr', this.parseEnumAttrBracket.bind(this));
  23572. this.registerCustomAttribute('TensorRT_GatherModeAttr', this.parseEnumAttrBracket.bind(this));
  23573. this.registerCustomAttribute('TensorRT_FillOperationAttr', this.parseEnumAttrBracket.bind(this));
  23574. this.registerCustomAttribute('TensorRT_ElementWiseOperationAttr', this.parseEnumAttrBracket.bind(this));
  23575. this.registerCustomAttribute('TensorRT_ActivationTypeAttr', this.parseEnumAttrBracket.bind(this));
  23576. this.registerCustomAttribute('TensorRT_UnaryOperationAttr', this.parseEnumAttrBracket.bind(this));
  23577. this.registerCustomAttribute('TensorRT_TripLimitAttr', this.parseEnumAttrBracket.bind(this));
  23578. this.registerCustomAttribute('TensorRT_PoolingTypeAttr', this.parseEnumAttrBracket.bind(this));
  23579. this.registerCustomDirective('StaticIndexI64Array', this.parseStaticIndexI64Array.bind(this));
  23580. this.registerCustomDirective('StaticIndexI32Array', this.parseStaticIndexI32Array.bind(this));
  23581. }
  23582. parseEnumAttrBracket(parser) {
  23583. if (parser.getToken().is(_.Token.less)) {
  23584. parser.parseLess();
  23585. const value = parser.getToken().getSpelling().str();
  23586. parser.consumeToken(_.Token.bare_identifier);
  23587. parser.parseGreater();
  23588. return { value };
  23589. }
  23590. return null;
  23591. }
  23592. parseStaticIndexI64Array(parser, op, attrName = 'broadcast_dims') {
  23593. const values = [];
  23594. do {
  23595. const value = parser.parseOptionalInteger();
  23596. if (value === null) {
  23597. break;
  23598. }
  23599. values.push(value);
  23600. } while (parser.parseOptionalComma());
  23601. op.addAttribute(attrName, values);
  23602. }
  23603. parseStaticIndexI32Array(parser, op, attrName = 'static_values') {
  23604. const values = [];
  23605. do {
  23606. const value = parser.parseOptionalInteger();
  23607. if (value === null) {
  23608. break;
  23609. }
  23610. values.push(value);
  23611. } while (parser.parseOptionalComma());
  23612. op.addAttribute(attrName, values);
  23613. }
  23614. parseOperation(parser, result) {
  23615. if (result.op === 'tensorrt.for') {
  23616. return this.parseForOp(parser, result);
  23617. }
  23618. return super.parseOperation(parser, result);
  23619. }
  23620. parseForOp(parser, result) {
  23621. const inductionVar = parser.parseOperand();
  23622. parser.parseEqual();
  23623. const unresolvedLb = parser.parseOperand();
  23624. parser.resolveOperand(unresolvedLb, null, result.operands);
  23625. parser.parseKeyword('to');
  23626. const unresolvedUb = parser.parseOperand();
  23627. parser.resolveOperand(unresolvedUb, null, result.operands);
  23628. parser.parseKeyword('step');
  23629. const unresolvedStep = parser.parseOperand();
  23630. parser.resolveOperand(unresolvedStep, null, result.operands);
  23631. parser.parseKeyword('init');
  23632. const regionArgs = [{ name: inductionVar.name, type: null }];
  23633. if (parser.parseOptionalLParen()) {
  23634. while (!parser.parseOptionalRParen()) {
  23635. let iterArgName = null;
  23636. if (parser.getToken().is(_.Token.percent_identifier)) {
  23637. const iterArg = parser.parseOperand();
  23638. iterArgName = iterArg.name;
  23639. }
  23640. if (parser.parseOptionalEqual()) {
  23641. if (parser.getToken().is(_.Token.percent_identifier)) {
  23642. const unresolvedInit = parser.parseOperand();
  23643. parser.resolveOperand(unresolvedInit, null, result.operands);
  23644. if (iterArgName) {
  23645. regionArgs.push({ name: iterArgName, type: null });
  23646. }
  23647. }
  23648. }
  23649. parser.parseOptionalComma();
  23650. }
  23651. }
  23652. result.addTypes(parser.parseOptionalArrowTypeList());
  23653. if (parser.getToken().is(_.Token.l_brace)) {
  23654. const region = result.addRegion();
  23655. parser.parseRegion(region, regionArgs);
  23656. }
  23657. parser.parseOptionalAttrDict(result.attributes);
  23658. return true;
  23659. }
  23660. };
  23661. _.executor = {};
  23662. _.executor.TableType = class extends _.Type {
  23663. constructor(body) {
  23664. super(null);
  23665. this.body = body;
  23666. }
  23667. toString() {
  23668. const bodyStr = this.body.map((t) => t.toString()).join(', ');
  23669. return `!executor.table<${bodyStr}>`;
  23670. }
  23671. };
  23672. _.executor.ExecutorDialect = class extends _.Dialect {
  23673. constructor(operations) {
  23674. super(operations, 'executor');
  23675. this.registerCustomType('Executor_Table', this.parseTable.bind(this));
  23676. this.registerCustomDirective('ExecutorMixedIndices', this.parseExecutorMixedIndices.bind(this));
  23677. }
  23678. parseOperation(parser, result) {
  23679. if (result.op === 'executor.func') {
  23680. parser.parseFunctionOp(result, true);
  23681. return true;
  23682. }
  23683. return super.parseOperation(parser, result);
  23684. }
  23685. inferResultTypes(op, vars) {
  23686. if (op.op === 'executor.table.get') {
  23687. // ExtractTableValueOp::inferReturnTypes
  23688. const tableType = op.operands[0]?.type;
  23689. const index = op.attributes.get('index');
  23690. if (tableType instanceof _.executor.TableType && index !== undefined) {
  23691. const idx = typeof index === 'number' ? index : parseInt(index, 10);
  23692. if (idx >= 0 && idx < tableType.body.length) {
  23693. op.addTypes([tableType.body[idx]]);
  23694. return;
  23695. }
  23696. }
  23697. }
  23698. super.inferResultTypes(op, vars);
  23699. }
  23700. parseType(parser, dialect) {
  23701. const typeName = parser.parseOptionalKeyword();
  23702. if (!typeName) {
  23703. return null;
  23704. }
  23705. if (typeName === 'table') {
  23706. if (parser.getToken().is(_.Token.less)) {
  23707. parser.parseLess();
  23708. const body = [];
  23709. if (parser.getToken().isNot(_.Token.greater)) {
  23710. do {
  23711. const elementType = parser.parseType();
  23712. body.push(elementType);
  23713. } while (parser.parseOptionalComma());
  23714. }
  23715. parser.parseGreater();
  23716. return new _.executor.TableType(body);
  23717. }
  23718. return new _.executor.TableType([]);
  23719. }
  23720. let type = `!${dialect}.${typeName}`;
  23721. if (parser.getToken().is(_.Token.less)) {
  23722. type += parser.skip('<');
  23723. }
  23724. return new _.Type(type);
  23725. }
  23726. parseTable(parser) {
  23727. if (parser.getToken().is(_.Token.less)) {
  23728. parser.parseLess();
  23729. const body = [];
  23730. if (parser.getToken().isNot(_.Token.greater)) {
  23731. do {
  23732. const elementType = parser.parseType();
  23733. body.push(elementType);
  23734. } while (parser.parseOptionalComma());
  23735. }
  23736. parser.parseGreater();
  23737. return new _.executor.TableType(body);
  23738. }
  23739. return null;
  23740. }
  23741. parseExecutorMixedIndices(parser, op /*, args */) {
  23742. const unresolvedOperands = [];
  23743. do {
  23744. if (parser.getToken().is(_.Token.percent_identifier)) {
  23745. unresolvedOperands.push(parser.parseOperand());
  23746. } else {
  23747. parser.parseAttribute();
  23748. }
  23749. } while (parser.parseOptionalComma());
  23750. for (const unresolved of unresolvedOperands) {
  23751. parser.resolveOperand(unresolved, null, op.operands);
  23752. }
  23753. }
  23754. };
  23755. _.TFRTTestDialect = class extends _.Dialect {
  23756. constructor(operations) {
  23757. super(operations, 'tfrt_test');
  23758. this.registerCustomDirective('OptionalLoc', this.parseOptionalLoc.bind(this));
  23759. this.registerCustomDirective('DummyRegionRef', this.parseDummyRegionRef.bind(this));
  23760. this.registerCustomDirective('DummySuccessorRef', this.parseDummySuccessorRef.bind(this));
  23761. }
  23762. parseOptionalLoc(parser, op, attrName = 'loc') {
  23763. const loc = parser.parseOptionalLocationSpecifier();
  23764. if (loc) {
  23765. op.addAttribute(attrName, loc);
  23766. } else {
  23767. op.addAttribute(attrName, parser.location());
  23768. }
  23769. }
  23770. parseDummyRegionRef() {
  23771. }
  23772. parseDummySuccessorRef() {
  23773. }
  23774. parseOperation(parser, result) {
  23775. const opInfo = result.name.getRegisteredInfo();
  23776. if (!opInfo) {
  23777. return false;
  23778. }
  23779. if (opInfo.metadata.assemblyFormat === 'operands attr-dict') {
  23780. const unresolvedOperands = [];
  23781. while (parser.getToken().is(_.Token.percent_identifier)) {
  23782. unresolvedOperands.push(parser.parseOperand());
  23783. if (!parser.parseOptionalComma()) {
  23784. break;
  23785. }
  23786. }
  23787. if (parser.getToken().is(_.Token.l_brace)) {
  23788. parser.parseAttributeDict(result.attributes);
  23789. }
  23790. for (const unresolved of unresolvedOperands) {
  23791. parser.resolveOperand(unresolved, null, result.operands);
  23792. }
  23793. this.inferResultTypes(result, new Map());
  23794. return true;
  23795. }
  23796. if (result.op === 'tfrt_test.do.async') {
  23797. if (parser.getToken().is(_.Token.percent_identifier)) {
  23798. const unresolvedOperands = parser.parseOperandList('none');
  23799. parser.resolveOperands(unresolvedOperands, unresolvedOperands.map(() => null), result.operands);
  23800. }
  23801. if (parser.parseOptionalColon()) {
  23802. const type = parser.parseFunctionType();
  23803. if (type && type.results) {
  23804. type.results.forEach((resultType) => {
  23805. result.addTypes([resultType]);
  23806. });
  23807. }
  23808. }
  23809. if (parser.getToken().is(_.Token.l_brace)) {
  23810. const region = result.addRegion();
  23811. parser.parseRegion(region);
  23812. }
  23813. return true;
  23814. }
  23815. if (result.op === 'tfrt_test.benchmark') {
  23816. if (parser.getToken().is(_.Token.string)) {
  23817. const name = parser.getToken().getSpelling().str();
  23818. parser.consumeToken(_.Token.string);
  23819. result.addAttribute('name', name);
  23820. }
  23821. parser.parseLParen();
  23822. while (parser.getToken().is(_.Token.percent_identifier)) {
  23823. const unresolved = parser.parseOperand();
  23824. let type = null;
  23825. if (parser.parseOptionalColon()) {
  23826. type = parser.parseType();
  23827. }
  23828. parser.resolveOperand(unresolved, type, result.operands);
  23829. if (!parser.parseOptionalComma()) {
  23830. break;
  23831. }
  23832. }
  23833. parser.parseRParen();
  23834. while (parser.getToken().is(_.Token.bare_identifier) && parser.getToken().isNot(_.Token.l_brace)) {
  23835. const name = parser.getToken().getSpelling().str();
  23836. parser.consumeToken(_.Token.bare_identifier);
  23837. parser.parseEqual();
  23838. let value = null;
  23839. if (parser.getToken().is(_.Token.integer)) {
  23840. value = parser.parseInteger();
  23841. } else if (parser.getToken().is(_.Token.string)) {
  23842. value = parser.getToken().getSpelling().str();
  23843. parser.consumeToken(_.Token.string);
  23844. } else {
  23845. value = parser.getToken().getSpelling().str();
  23846. parser.consumeToken(_.Token.bare_identifier);
  23847. }
  23848. result.addAttribute(name, value);
  23849. parser.parseOptionalComma();
  23850. }
  23851. if (parser.getToken().is(_.Token.l_brace)) {
  23852. const region = result.addRegion();
  23853. parser.parseRegion(region);
  23854. }
  23855. result.addTypes([new _.Type('!tfrt.chain')]);
  23856. return true;
  23857. }
  23858. return super.parseOperation(parser, result);
  23859. }
  23860. };
  23861. _.XeVMDialect = class extends _.Dialect {
  23862. constructor(operations) {
  23863. super(operations, 'xevm');
  23864. }
  23865. };
  23866. _.VMVXDialect = class extends _.Dialect {
  23867. constructor(operations) {
  23868. super(operations, 'vmvx');
  23869. }
  23870. };
  23871. _.MLRTDialect = class extends _.Dialect {
  23872. constructor(operations) {
  23873. super(operations, 'mlrt');
  23874. }
  23875. };
  23876. _.TFRTTensorDialect = class extends _.Dialect {
  23877. constructor(operations) {
  23878. super(operations, 'tfrt_tensor');
  23879. }
  23880. };
  23881. _.TFRTDHTDialect = class extends _.Dialect {
  23882. constructor(operations) {
  23883. super(operations, 'tfrt_dht');
  23884. }
  23885. };
  23886. _.TFDDialect = class extends _.Dialect {
  23887. constructor(operations) {
  23888. super(operations, 'tfd');
  23889. }
  23890. };
  23891. _.ACCDialect = class extends _.Dialect {
  23892. constructor(operations) {
  23893. super(operations, 'acc');
  23894. this.registerCustomDirective('Var', this.parseVar.bind(this));
  23895. this.registerCustomDirective('AccVar', this.parseAccVar.bind(this));
  23896. this.registerCustomDirective('VarPtrType', this.parseVarPtrType.bind(this));
  23897. this.registerCustomDirective('DeviceTypeOperandsWithKeywordOnly', this.parseDeviceTypeOperandsWithKeywordOnly.bind(this));
  23898. this.registerCustomDirective('LoopControl', this.parseLoopControl.bind(this));
  23899. this.registerCustomDirective('WaitClause', this.parseWaitClause.bind(this));
  23900. this.registerCustomDirective('NumGangs', this.parseNumGangs.bind(this));
  23901. this.registerCustomDirective('DeviceTypeOperands', this.parseDeviceTypeOperands.bind(this));
  23902. this.registerCustomDirective('GangClause', this.parseGangClause.bind(this));
  23903. this.registerCustomDirective('CombinedConstructsLoop', this.parseCombinedConstructsLoop.bind(this));
  23904. this.registerCustomDirective('RecipeSym', this.parseRecipeSym.bind(this));
  23905. this.registerCustomDirective('OperandWithKeywordOnly', this.parseOperandWithKeywordOnly.bind(this));
  23906. this.registerCustomDirective('OperandsWithKeywordOnly', this.parseOperandsWithKeywordOnly.bind(this));
  23907. this.registerCustomDirective('DeviceTypeOperandsWithSegment', this.parseDeviceTypeOperandsWithSegment.bind(this));
  23908. this.registerCustomDirective('BindName', this.parseBindName.bind(this));
  23909. this.registerCustomDirective('RoutineGangClause', this.parseRoutineGangClause.bind(this));
  23910. this.registerCustomDirective('DeviceTypeArrayAttr', this.parseDeviceTypeArrayAttr.bind(this));
  23911. }
  23912. // custom<Var>($var) - receives ctx.get('var').operands
  23913. parseVar(parser, op, operands) {
  23914. if (!parser.parseOptionalKeyword('varPtr')) {
  23915. parser.parseKeyword('var');
  23916. }
  23917. parser.parseLParen();
  23918. operands.push(parser.parseOperand());
  23919. }
  23920. // custom<AccVar>($accVar, type($accVar)) - self-contained with type inline
  23921. parseAccVar(parser, op, operands, types) {
  23922. if (!parser.parseOptionalKeyword('accPtr')) {
  23923. parser.parseKeyword('accVar');
  23924. }
  23925. parser.parseLParen();
  23926. operands.push(parser.parseOperand());
  23927. parser.parseColon();
  23928. types.push(parser.parseType());
  23929. parser.parseRParen();
  23930. }
  23931. // custom<VarPtrType>(type($var), $varType) - receives ctx.get('var').types
  23932. parseVarPtrType(parser, op, types, varTypeAttrName) {
  23933. const type = parser.parseType();
  23934. types.push(type);
  23935. parser.parseRParen();
  23936. if (parser.parseOptionalKeyword('varType')) {
  23937. parser.parseLParen();
  23938. const varType = parser.parseType();
  23939. op.addAttribute(varTypeAttrName || 'varType', varType);
  23940. parser.parseRParen();
  23941. }
  23942. }
  23943. parseDeviceTypeOperandsWithKeywordOnly(parser, op, operands, types, deviceTypesVar, keywordOnlyVar) {
  23944. if (!parser.parseOptionalLParen()) {
  23945. op.addAttribute(keywordOnlyVar, [{ value: 'none' }]);
  23946. return;
  23947. }
  23948. const keywordOnlyAttrs = [];
  23949. let needComma = false;
  23950. if (parser.parseOptionalLSquare()) {
  23951. while (parser.getToken().isNot(_.Token.r_square)) {
  23952. const attr = parser.parseAttribute();
  23953. keywordOnlyAttrs.push(attr);
  23954. parser.parseOptionalComma();
  23955. }
  23956. parser.parseRSquare();
  23957. needComma = true;
  23958. }
  23959. if (keywordOnlyAttrs.length > 0) {
  23960. op.addAttribute(keywordOnlyVar, keywordOnlyAttrs);
  23961. }
  23962. if (needComma) {
  23963. parser.parseOptionalComma();
  23964. }
  23965. const unresolvedOperands = [];
  23966. const operandTypes = [];
  23967. const deviceTypes = [];
  23968. while (parser.getToken().isNot(_.Token.r_paren)) {
  23969. const operand = parser.parseOperand();
  23970. parser.parseColon();
  23971. const type = parser.parseType();
  23972. unresolvedOperands.push(operand);
  23973. operandTypes.push(type);
  23974. if (parser.parseOptionalLSquare()) {
  23975. const deviceType = parser.parseAttribute();
  23976. deviceTypes.push(deviceType);
  23977. parser.parseRSquare();
  23978. } else {
  23979. deviceTypes.push({ value: 'none' });
  23980. }
  23981. if (!parser.parseOptionalComma()) {
  23982. break;
  23983. }
  23984. }
  23985. parser.parseRParen();
  23986. parser.resolveOperands(unresolvedOperands, operandTypes, op.operands);
  23987. if (deviceTypes.length > 0) {
  23988. op.addAttribute(deviceTypesVar, deviceTypes);
  23989. }
  23990. }
  23991. parseLoopControl(parser, result) {
  23992. const inductionVars = [];
  23993. if (parser.parseOptionalKeyword('control')) {
  23994. parser.parseLParen();
  23995. while (parser.getToken().isNot(_.Token.r_paren)) {
  23996. const value = parser.parseOperand();
  23997. parser.parseColon();
  23998. const type = parser.parseType();
  23999. inductionVars.push({ value, type });
  24000. parser.parseOptionalComma();
  24001. }
  24002. parser.parseRParen();
  24003. parser.parseEqual();
  24004. parser.parseLParen();
  24005. const lowerbound = parser.parseOperandList();
  24006. const lowerboundTypes = parser.parseColonTypeList();
  24007. parser.resolveOperands(lowerbound, lowerboundTypes, result.operands);
  24008. parser.parseRParen();
  24009. parser.parseKeyword('to');
  24010. parser.parseLParen();
  24011. const upperbound = parser.parseOperandList();
  24012. const upperboundTypes = parser.parseColonTypeList();
  24013. parser.resolveOperands(upperbound, upperboundTypes, result.operands);
  24014. parser.parseRParen();
  24015. parser.parseKeyword('step');
  24016. parser.parseLParen();
  24017. const step = parser.parseOperandList();
  24018. const stepTypes = parser.parseColonTypeList();
  24019. parser.resolveOperands(step, stepTypes, result.operands);
  24020. parser.parseRParen();
  24021. }
  24022. const region = result.addRegion();
  24023. parser.parseRegion(region, inductionVars);
  24024. }
  24025. parseWaitClause(parser, result) {
  24026. if (parser.getToken().isNot(_.Token.l_paren)) {
  24027. return;
  24028. }
  24029. parser.parseLParen();
  24030. if (parser.parseOptionalLSquare()) {
  24031. while (!parser.parseOptionalRSquare()) {
  24032. parser.parseAttribute();
  24033. parser.parseOptionalComma();
  24034. }
  24035. if (parser.getToken().isNot(_.Token.r_paren)) {
  24036. parser.parseOptionalComma();
  24037. }
  24038. }
  24039. while (parser.getToken().isNot(_.Token.r_paren)) {
  24040. if (parser.parseOptionalLBrace()) {
  24041. parser.parseOptionalKeyword('devnum');
  24042. parser.parseOptionalColon();
  24043. while (!parser.parseOptionalRBrace()) {
  24044. const operand = parser.parseOperand();
  24045. parser.parseColon();
  24046. const type = parser.parseType();
  24047. parser.resolveOperand(operand, type, result.operands);
  24048. parser.parseOptionalComma();
  24049. }
  24050. if (parser.parseOptionalLSquare()) {
  24051. parser.parseAttribute();
  24052. parser.parseRSquare();
  24053. }
  24054. }
  24055. parser.parseOptionalComma();
  24056. }
  24057. parser.parseRParen();
  24058. }
  24059. parseNumGangs(parser, result) {
  24060. while (parser.parseOptionalLBrace()) {
  24061. while (!parser.parseOptionalRBrace()) {
  24062. const operand = parser.parseOperand();
  24063. parser.parseColon();
  24064. const type = parser.parseType();
  24065. parser.resolveOperand(operand, type, result.operands);
  24066. parser.parseOptionalComma();
  24067. }
  24068. if (parser.parseOptionalLSquare()) {
  24069. parser.parseAttribute();
  24070. parser.parseRSquare();
  24071. }
  24072. parser.parseOptionalComma();
  24073. }
  24074. }
  24075. parseDeviceTypeOperands(parser, result) {
  24076. while (parser.getToken().is(_.Token.percent_identifier)) {
  24077. const operand = parser.parseOperand();
  24078. parser.parseColon();
  24079. const type = parser.parseType();
  24080. parser.resolveOperand(operand, type, result.operands);
  24081. if (parser.parseOptionalLSquare()) {
  24082. parser.parseAttribute();
  24083. parser.parseRSquare();
  24084. }
  24085. parser.parseOptionalComma();
  24086. }
  24087. }
  24088. parseGangClause(parser, op, gangOperands, gangTypes, gangArgTypeVar, gangDeviceTypeVar, gangSegmentsVar, gangOnlyVar) {
  24089. if (!parser.parseOptionalLParen()) {
  24090. op.addAttribute(gangOnlyVar, [{ value: 'none' }]);
  24091. return;
  24092. }
  24093. const gangOnlyAttrs = [];
  24094. let needComma = false;
  24095. if (parser.parseOptionalLSquare()) {
  24096. while (parser.getToken().isNot(_.Token.r_square)) {
  24097. const attr = parser.parseAttribute();
  24098. gangOnlyAttrs.push(attr);
  24099. parser.parseOptionalComma();
  24100. }
  24101. parser.parseRSquare();
  24102. needComma = true;
  24103. }
  24104. if (gangOnlyAttrs.length > 0) {
  24105. op.addAttribute(gangOnlyVar, gangOnlyAttrs);
  24106. }
  24107. if (needComma) {
  24108. parser.parseOptionalComma();
  24109. }
  24110. const gangArgTypes = [];
  24111. const deviceTypes = [];
  24112. const segments = [];
  24113. while (parser.parseOptionalLBrace()) {
  24114. let segmentCount = 0;
  24115. while (parser.getToken().isNot(_.Token.r_brace)) {
  24116. let argType = 'Num';
  24117. if (parser.parseOptionalKeyword('num')) {
  24118. parser.parseEqual();
  24119. argType = 'Num';
  24120. } else if (parser.parseOptionalKeyword('dim')) {
  24121. parser.parseEqual();
  24122. argType = 'Dim';
  24123. } else if (parser.parseOptionalKeyword('static')) {
  24124. parser.parseEqual();
  24125. argType = 'Static';
  24126. }
  24127. gangArgTypes.push({ value: argType });
  24128. const operand = parser.parseOperand();
  24129. parser.parseColon();
  24130. const type = parser.parseType();
  24131. parser.resolveOperand(operand, type, op.operands);
  24132. segmentCount++;
  24133. if (!parser.parseOptionalComma()) {
  24134. break;
  24135. }
  24136. }
  24137. parser.parseRBrace();
  24138. segments.push(segmentCount);
  24139. if (parser.parseOptionalLSquare()) {
  24140. const deviceType = parser.parseAttribute();
  24141. deviceTypes.push(deviceType);
  24142. parser.parseRSquare();
  24143. } else {
  24144. deviceTypes.push({ value: 'none' });
  24145. }
  24146. if (!parser.parseOptionalComma()) {
  24147. break;
  24148. }
  24149. }
  24150. parser.parseRParen();
  24151. if (gangArgTypes.length > 0) {
  24152. op.addAttribute('gangOperandsArgType', gangArgTypes);
  24153. }
  24154. if (deviceTypes.length > 0) {
  24155. op.addAttribute('gangOperandsDeviceType', deviceTypes);
  24156. }
  24157. if (segments.length > 0) {
  24158. op.addAttribute('gangOperandsSegments', segments);
  24159. }
  24160. }
  24161. parseCombinedConstructsLoop(parser, result) {
  24162. const attr = parser.parseAttribute();
  24163. result.addAttribute('combined', attr);
  24164. }
  24165. parseRecipeSym(parser, result) {
  24166. const attr = parser.parseAttribute();
  24167. result.addAttribute('recipe', attr);
  24168. }
  24169. parseOperandWithKeywordOnly(parser, result) {
  24170. if (parser.getToken().isNot(_.Token.l_paren)) {
  24171. return;
  24172. }
  24173. parser.parseLParen();
  24174. if (parser.parseOptionalLSquare()) {
  24175. while (!parser.parseOptionalRSquare()) {
  24176. parser.parseAttribute();
  24177. parser.parseOptionalComma();
  24178. }
  24179. if (parser.getToken().isNot(_.Token.r_paren)) {
  24180. parser.parseOptionalComma();
  24181. }
  24182. }
  24183. while (parser.getToken().isNot(_.Token.r_paren)) {
  24184. const operand = parser.parseOperand();
  24185. parser.parseColon();
  24186. const type = parser.parseType();
  24187. parser.resolveOperand(operand, type, result.operands);
  24188. if (parser.parseOptionalLSquare()) {
  24189. parser.parseAttribute();
  24190. parser.parseRSquare();
  24191. }
  24192. parser.parseOptionalComma();
  24193. }
  24194. parser.parseRParen();
  24195. }
  24196. parseOperandsWithKeywordOnly(parser, result) {
  24197. // Handles format: (%v1, %v2 : t1, t2) where all operands are listed before colon
  24198. // and all types are listed after colon
  24199. if (parser.getToken().isNot(_.Token.l_paren)) {
  24200. return;
  24201. }
  24202. parser.parseLParen();
  24203. if (parser.getToken().is(_.Token.r_paren)) {
  24204. parser.parseRParen();
  24205. return;
  24206. }
  24207. const unresolvedOperands = [];
  24208. do {
  24209. unresolvedOperands.push(parser.parseOperand());
  24210. } while (parser.parseOptionalComma() && parser.getToken().isNot(_.Token.colon));
  24211. parser.parseColon();
  24212. const types = [];
  24213. for (let i = 0; i < unresolvedOperands.length; i++) {
  24214. if (i > 0) {
  24215. parser.parseComma();
  24216. }
  24217. types.push(parser.parseType());
  24218. }
  24219. parser.resolveOperands(unresolvedOperands, types, result.operands);
  24220. parser.parseRParen();
  24221. }
  24222. parseDeviceTypeOperandsWithSegment(parser, result) {
  24223. this.parseNumGangs(parser, result);
  24224. }
  24225. parseBindName(parser, result) {
  24226. while (parser.getToken().isNot(_.Token.r_paren)) {
  24227. const attr = parser.parseAttribute();
  24228. if (parser.parseOptionalLSquare()) {
  24229. parser.parseAttribute();
  24230. parser.parseRSquare();
  24231. }
  24232. result.addAttribute('bind', attr);
  24233. parser.parseOptionalComma();
  24234. }
  24235. }
  24236. parseRoutineGangClause(parser, result) {
  24237. if (parser.parseOptionalLParen()) {
  24238. while (parser.getToken().isNot(_.Token.r_paren)) {
  24239. if (parser.parseOptionalKeyword('dim')) {
  24240. parser.parseColon();
  24241. }
  24242. const value = parser.parseAttribute();
  24243. if (parser.parseOptionalLSquare()) {
  24244. parser.parseAttribute();
  24245. parser.parseRSquare();
  24246. }
  24247. result.addAttribute('gangDim', value);
  24248. parser.parseOptionalComma();
  24249. }
  24250. parser.parseRParen();
  24251. } else if (parser.parseOptionalLSquare()) {
  24252. while (!parser.parseOptionalRSquare()) {
  24253. parser.parseAttribute();
  24254. parser.parseOptionalComma();
  24255. }
  24256. }
  24257. }
  24258. parseDeviceTypeArrayAttr(parser) {
  24259. if (parser.parseOptionalLSquare()) {
  24260. while (!parser.parseOptionalRSquare()) {
  24261. parser.parseAttribute();
  24262. parser.parseOptionalComma();
  24263. }
  24264. }
  24265. }
  24266. };
  24267. _.smt = {};
  24268. _.smt.BitVectorType = class extends _.Type {
  24269. constructor(width) {
  24270. super(null);
  24271. this.width = width;
  24272. }
  24273. toString() {
  24274. return `!smt.bv<${this.width}>`;
  24275. }
  24276. };
  24277. _.smt.SMTDialect = class extends _.Dialect {
  24278. constructor(operations) {
  24279. super(operations, 'smt');
  24280. }
  24281. parseOperation(parser, result) {
  24282. if (result.op === 'smt.eq' || result.op === 'smt.distinct') {
  24283. const unresolvedOperands = parser.parseOperandList();
  24284. parser.parseOptionalAttrDict(result.attributes);
  24285. parser.parseColon();
  24286. const type = parser.parseType();
  24287. const types = unresolvedOperands.map(() => type);
  24288. parser.resolveOperands(unresolvedOperands, types, result.operands);
  24289. result.addTypes([new _.Type('!smt.bool')]);
  24290. return true;
  24291. }
  24292. if (result.op === 'smt.bv.repeat') {
  24293. const count = parser.parseInteger();
  24294. result.addAttribute('count', count);
  24295. parser.parseKeyword('times');
  24296. const unresolvedOperand = parser.parseOperand();
  24297. parser.parseOptionalAttrDict(result.attributes);
  24298. parser.parseColon();
  24299. const inputType = parser.parseType();
  24300. parser.resolveOperand(unresolvedOperand, inputType, result.operands);
  24301. // RepeatOp::parse - result width = input width * count
  24302. const inputWidth = inputType instanceof _.smt.BitVectorType ? inputType.width : 0;
  24303. const resultWidth = inputWidth * count;
  24304. result.addTypes([new _.smt.BitVectorType(resultWidth)]);
  24305. return true;
  24306. }
  24307. if (result.op === 'smt.int.constant') {
  24308. const value = parser.parseInteger();
  24309. result.addAttribute('value', value);
  24310. parser.parseOptionalAttrDict(result.attributes);
  24311. result.addTypes([new _.Type('!smt.int')]);
  24312. return true;
  24313. }
  24314. return super.parseOperation(parser, result);
  24315. }
  24316. parseType(parser) {
  24317. const typeName = parser.parseOptionalKeyword();
  24318. if (typeName === 'bv' && parser.getToken().is(_.Token.less)) {
  24319. parser.parseLess();
  24320. const width = parseInt(parser.getToken().getSpelling().str(), 10);
  24321. parser.consumeToken(_.Token.integer);
  24322. parser.parseGreater();
  24323. return new _.smt.BitVectorType(width);
  24324. }
  24325. if (typeName) {
  24326. let type = `!smt.${typeName}`;
  24327. if (parser.getToken().is(_.Token.less)) {
  24328. type += parser.skip('<');
  24329. }
  24330. return new _.Type(type);
  24331. }
  24332. return null;
  24333. }
  24334. inferResultTypes(op, vars) {
  24335. if (op.op === 'smt.bv.concat') {
  24336. // ConcatOp::inferReturnTypes - result width = lhs width + rhs width
  24337. if (op.operands.length >= 2) {
  24338. const lhsType = op.operands[0].type;
  24339. const rhsType = op.operands[1].type;
  24340. const lhsWidth = lhsType instanceof _.smt.BitVectorType ? lhsType.width : 0;
  24341. const rhsWidth = rhsType instanceof _.smt.BitVectorType ? rhsType.width : 0;
  24342. const resultWidth = lhsWidth + rhsWidth;
  24343. op.addTypes([new _.smt.BitVectorType(resultWidth)]);
  24344. return;
  24345. }
  24346. }
  24347. super.inferResultTypes(op, vars);
  24348. }
  24349. };
  24350. _.MPMDDialect = class extends _.Dialect {
  24351. constructor(operations) {
  24352. super(operations, 'mpmd');
  24353. this.registerCustomType('mesh_tensor', this.parseMeshTensorType.bind(this));
  24354. }
  24355. parseOperation(parser, result) {
  24356. if (result.op === 'mpmd.named_computation') {
  24357. return this.parseNamedComputationOp(parser, result);
  24358. }
  24359. if (result.op === 'mpmd.fragment') {
  24360. return this.parseFragmentOp(parser, result);
  24361. }
  24362. if (result.op === 'mpmd.fragment_call') {
  24363. return this.parseFragmentCallOp(parser, result);
  24364. }
  24365. if (result.op === 'mpmd.for') {
  24366. return this.parseForOp(parser, result);
  24367. }
  24368. return super.parseOperation(parser, result);
  24369. }
  24370. parseNamedComputationOp(parser, result) {
  24371. // mpmd.named_computation<"name"(count)> (%inputs) (%block_args) { region } : (types) -> types
  24372. parser.parseLess();
  24373. // Parse single UserOriginAttr in short format: "name"(count)
  24374. const origin = this.parseUserOriginAttr(parser);
  24375. result.addAttribute('origin', origin);
  24376. parser.parseGreater();
  24377. const unresolvedInputs = parser.parseOperandList('paren');
  24378. const entryArguments = this.parseBlockArguments(parser);
  24379. if (parser.getToken().is(_.Token.l_brace)) {
  24380. const region = result.addRegion();
  24381. parser.parseRegion(region, entryArguments);
  24382. }
  24383. if (parser.parseOptionalColon()) {
  24384. const type = parser.parseType();
  24385. if (type instanceof _.FunctionType) {
  24386. parser.resolveOperands(unresolvedInputs, type.inputs, result.operands);
  24387. result.addTypes(type.results);
  24388. }
  24389. }
  24390. return true;
  24391. }
  24392. parseBlockArguments(parser) {
  24393. return parser.parseArgumentList('optionalParen', true);
  24394. }
  24395. parseFragmentOp(parser, result) {
  24396. // mpmd.fragment<mesh="m1", origin=["f1"], stage_id=N> (%inputs) {attrs} (%block_args) { region } : (types) -> type
  24397. parser.parseLess();
  24398. while (parser.getToken().isNot(_.Token.greater)) {
  24399. const attrName = parser.getToken().getSpelling().str();
  24400. parser.consumeToken(_.Token.bare_identifier);
  24401. parser.parseEqual();
  24402. // Use custom parser for origin attribute (array of UserOriginAttr)
  24403. const attrValue = attrName === 'origin' ? this.parseOriginArray(parser) : parser.parseAttribute();
  24404. result.addAttribute(attrName, attrValue);
  24405. parser.parseOptionalComma();
  24406. }
  24407. parser.parseGreater();
  24408. const unresolvedInputs = parser.parseOperandList('paren');
  24409. parser.parseOptionalAttrDict(result.attributes);
  24410. const entryArguments = this.parseBlockArguments(parser);
  24411. if (parser.getToken().is(_.Token.l_brace)) {
  24412. const region = result.addRegion();
  24413. parser.parseRegion(region, entryArguments);
  24414. }
  24415. if (parser.parseOptionalColon()) {
  24416. const type = parser.parseType();
  24417. if (type instanceof _.FunctionType) {
  24418. parser.resolveOperands(unresolvedInputs, type.inputs, result.operands);
  24419. result.addTypes(type.results);
  24420. }
  24421. }
  24422. return true;
  24423. }
  24424. parseFragmentCallOp(parser, result) {
  24425. // mpmd.fragment_call<mesh="m1", origin=["f1"]> @callee(%args) {attrs} : (types) -> type
  24426. parser.parseLess();
  24427. while (parser.getToken().isNot(_.Token.greater)) {
  24428. const attrName = parser.getToken().getSpelling().str();
  24429. parser.consumeToken(_.Token.bare_identifier);
  24430. parser.parseEqual();
  24431. // Use custom parser for origin attribute (array of UserOriginAttr)
  24432. const attrValue = attrName === 'origin' ? this.parseOriginArray(parser) : parser.parseAttribute();
  24433. result.addAttribute(attrName, attrValue);
  24434. parser.parseOptionalComma();
  24435. }
  24436. parser.parseGreater();
  24437. const callee = parser.getToken().getSpelling().str();
  24438. parser.consumeToken(_.Token.at_identifier);
  24439. result.addAttribute('callee', callee);
  24440. const unresolvedArgs = parser.parseOperandList('paren');
  24441. if (parser.getToken().is(_.Token.l_brace)) {
  24442. parser.parseAttributeDict(result.attributes);
  24443. }
  24444. if (parser.parseOptionalColon()) {
  24445. const type = parser.parseType();
  24446. if (type instanceof _.FunctionType) {
  24447. parser.resolveOperands(unresolvedArgs, type.inputs, result.operands);
  24448. result.addTypes(type.results);
  24449. }
  24450. }
  24451. return true;
  24452. }
  24453. parseForOp(parser, result) {
  24454. // Use parseOperandList for simple operand list (no types in syntax)
  24455. const inputs = parser.parseOperandList('paren');
  24456. const types = inputs.map(() => null);
  24457. parser.resolveOperands(inputs, types, result.operands);
  24458. parser.parseOptionalAttrDict(result.attributes);
  24459. const entryArguments = this.parseBlockArguments(parser);
  24460. if (parser.getToken().is(_.Token.l_brace)) {
  24461. const region = result.addRegion();
  24462. parser.parseRegion(region, entryArguments);
  24463. }
  24464. if (parser.parseOptionalColon()) {
  24465. const resultTypes = [];
  24466. do {
  24467. resultTypes.push(parser.parseType());
  24468. } while (parser.parseOptionalComma());
  24469. result.addTypes(resultTypes);
  24470. }
  24471. return true;
  24472. }
  24473. parseMeshTensorType(parser, prefix) {
  24474. // Parse !mpmd.mesh_tensor<"mesh_name", tensor<shape>, sharding=<...>>
  24475. parser.parseLess();
  24476. const meshName = parser.parseString();
  24477. parser.parseComma();
  24478. const tensorType = parser.parseType();
  24479. const result = { name: prefix, meshName, tensorType };
  24480. if (parser.parseOptionalComma()) {
  24481. if (parser.parseOptionalKeyword('sharding')) {
  24482. parser.parseEqual();
  24483. result.sharding = parser.parseAttribute();
  24484. }
  24485. }
  24486. parser.parseGreater();
  24487. return result;
  24488. }
  24489. // Parse UserOriginAttr in short format: "name"(count) where (count) is optional
  24490. parseUserOriginAttr(parser) {
  24491. const name = parser.parseString();
  24492. let transposeCount = 0;
  24493. if (parser.parseOptionalLParen()) {
  24494. const count = parser.parseInteger();
  24495. transposeCount = count;
  24496. parser.parseRParen();
  24497. }
  24498. return { name, transposeCount };
  24499. }
  24500. parseOriginArray(parser) {
  24501. const origins = [];
  24502. parser.parseLSquare();
  24503. while (!parser.parseOptionalRSquare()) {
  24504. const origin = this.parseUserOriginAttr(parser);
  24505. origins.push(origin);
  24506. parser.parseOptionalComma();
  24507. }
  24508. return origins;
  24509. }
  24510. };
  24511. _.SdyDialect = class extends _.Dialect {
  24512. constructor(operations) {
  24513. super(operations, 'sdy');
  24514. this.registerCustomDirective('StrippedTensorShardingPerValueAttr', this.parseStrippedTensorShardingPerValueAttr.bind(this));
  24515. this.registerCustomDirective('SingleBlockRegionNoBlockId', this.parseSingleBlockRegionNoBlockId.bind(this));
  24516. this.registerCustomAttribute('Sdy_ListOfAxisRefLists', this.parseListOfAxisRefLists.bind(this));
  24517. this.registerCustomAttribute('Sdy_ManualAxes', this.parseManualAxes.bind(this));
  24518. this.registerCustomAttribute('Sdy_AllToAllParamList', this.parseAllToAllParamList.bind(this));
  24519. this.registerCustomAttribute('Sdy_TensorSharding', this.parseTensorShardingAttrWrap.bind(this));
  24520. this.registerCustomAttribute('Sdy_AxisRefList', this.parseAxisRefListWrap.bind(this));
  24521. }
  24522. parseOperation(parser, result) {
  24523. if (result.op === 'sdy.constant') {
  24524. return this.parseConstantOp(parser, result);
  24525. }
  24526. return super.parseOperation(parser, result);
  24527. }
  24528. parseStrippedTensorShardingPerValueAttr(parser, op, attrName) {
  24529. const shardings = [];
  24530. parser.parseLSquare();
  24531. while (!parser.parseOptionalRSquare()) {
  24532. const sharding = this.parseTensorShardingAttr(parser);
  24533. shardings.push(sharding);
  24534. parser.parseOptionalComma();
  24535. }
  24536. if (attrName) {
  24537. op.addAttribute(attrName, shardings);
  24538. }
  24539. return shardings;
  24540. }
  24541. parseSingleBlockRegionNoBlockId(parser, op /*, args */) {
  24542. const entryArguments = [];
  24543. if (parser.parseOptionalLParen()) {
  24544. while (!parser.parseOptionalRParen()) {
  24545. const value = parser.parseOperand();
  24546. let type = null;
  24547. const attrs = [];
  24548. if (parser.parseOptionalColon()) {
  24549. type = parser.parseType();
  24550. }
  24551. if (parser.getToken().is(_.Token.l_brace)) {
  24552. parser.parseAttributeDict(attrs);
  24553. }
  24554. entryArguments.push({ value, type, attributes: attrs.length > 0 ? attrs : undefined });
  24555. parser.parseOptionalComma();
  24556. }
  24557. }
  24558. const region = op.addRegion();
  24559. parser.parseRegion(region, entryArguments);
  24560. return region;
  24561. }
  24562. parseTensorShardingAttr(parser) {
  24563. parser.parseLess();
  24564. let meshOrRef = null;
  24565. if (parser.getToken().is(_.Token.at_identifier)) {
  24566. meshOrRef = parser.getToken().getSpelling().str();
  24567. parser.consumeToken(_.Token.at_identifier);
  24568. } else if (parser.parseOptionalKeyword('mesh')) {
  24569. meshOrRef = this.parseMeshAttr(parser);
  24570. } else {
  24571. throw new mlir.Error(`Expected '@' or 'mesh', but got '${parser.getTokenSpelling().str()}' ${parser.location()}`);
  24572. }
  24573. parser.parseComma();
  24574. const dimShardings = this.parseDimensionShardings(parser);
  24575. let replicatedAxes = null;
  24576. let unreducedAxes = null;
  24577. while (parser.parseOptionalComma()) {
  24578. if (parser.parseOptionalKeyword('replicated')) {
  24579. parser.parseEqual();
  24580. replicatedAxes = this.parseAxisRefList(parser);
  24581. } else if (parser.parseOptionalKeyword('unreduced')) {
  24582. parser.parseEqual();
  24583. unreducedAxes = this.parseAxisRefList(parser);
  24584. }
  24585. }
  24586. parser.parseGreater();
  24587. return { meshOrRef, dimShardings, replicatedAxes, unreducedAxes };
  24588. }
  24589. parseMeshAttr(parser) {
  24590. parser.parseLess();
  24591. const axes = [];
  24592. parser.parseLSquare();
  24593. while (!parser.parseOptionalRSquare()) {
  24594. const name = parser.parseString();
  24595. parser.parseEqual();
  24596. const size = parser.parseInteger();
  24597. axes.push({ name, size });
  24598. parser.parseOptionalComma();
  24599. }
  24600. let deviceIds = null;
  24601. if (parser.parseOptionalComma()) {
  24602. if (parser.parseOptionalKeyword('device_ids')) {
  24603. parser.parseEqual();
  24604. deviceIds = parser.parseAttribute().value;
  24605. }
  24606. }
  24607. parser.parseGreater();
  24608. return { axes, deviceIds };
  24609. }
  24610. parseDimensionShardings(parser) {
  24611. const dimShardings = [];
  24612. parser.parseLSquare();
  24613. while (!parser.parseOptionalRSquare()) {
  24614. const dimSharding = this.parseDimensionShardingAttr(parser);
  24615. dimShardings.push(dimSharding);
  24616. parser.parseOptionalComma();
  24617. }
  24618. return dimShardings;
  24619. }
  24620. parseDimensionShardingAttr(parser) {
  24621. const axes = [];
  24622. parser.parseLBrace();
  24623. let isClosed = true;
  24624. while (!parser.parseOptionalRBrace()) {
  24625. if (parser.getToken().is(_.Token.question)) {
  24626. parser.consumeToken(_.Token.question);
  24627. isClosed = false;
  24628. parser.parseRBrace();
  24629. break;
  24630. }
  24631. const axis = this.parseAxisRefAttr(parser);
  24632. axes.push(axis);
  24633. if (parser.parseOptionalComma()) {
  24634. if (parser.getToken().is(_.Token.question)) {
  24635. parser.consumeToken(_.Token.question);
  24636. isClosed = false;
  24637. parser.parseRBrace();
  24638. break;
  24639. }
  24640. }
  24641. }
  24642. let priority = null;
  24643. if (parser.getToken().is(_.Token.bare_identifier)) {
  24644. const tokenValue = parser.getTokenSpelling().str();
  24645. if (typeof tokenValue === 'string' && tokenValue.startsWith('p') && /^p\d+$/.test(tokenValue)) {
  24646. parser.consumeToken(_.Token.bare_identifier);
  24647. priority = parseInt(tokenValue.substring(1), 10);
  24648. }
  24649. }
  24650. return { axes, isClosed, priority };
  24651. }
  24652. parseAxisRefAttr(parser) {
  24653. const name = parser.parseString();
  24654. let subAxisInfo = null;
  24655. if (parser.parseOptionalColon()) {
  24656. subAxisInfo = this.parseSubAxisInfo(parser);
  24657. }
  24658. return { name, subAxisInfo };
  24659. }
  24660. parseSubAxisInfo(parser) {
  24661. parser.parseLParen();
  24662. const preSize = parser.parseInteger();
  24663. parser.parseRParen();
  24664. const size = parser.parseInteger();
  24665. return { preSize, size };
  24666. }
  24667. parseAxisRefList(parser) {
  24668. const axes = [];
  24669. parser.parseLBrace();
  24670. while (!parser.parseOptionalRBrace()) {
  24671. const axis = this.parseAxisRefAttr(parser);
  24672. axes.push(axis);
  24673. parser.parseOptionalComma();
  24674. }
  24675. return axes;
  24676. }
  24677. parseListOfAxisRefLists(parser) {
  24678. const lists = [];
  24679. parser.parseLSquare();
  24680. while (!parser.parseOptionalRSquare()) {
  24681. const list = this.parseAxisRefList(parser);
  24682. lists.push(list);
  24683. parser.parseOptionalComma();
  24684. }
  24685. return { value: lists };
  24686. }
  24687. parseManualAxes(parser) {
  24688. const axes = [];
  24689. parser.parseLBrace();
  24690. while (!parser.parseOptionalRBrace()) {
  24691. const axis = parser.parseString();
  24692. axes.push(axis);
  24693. parser.parseOptionalComma();
  24694. }
  24695. return { value: axes };
  24696. }
  24697. parseAllToAllParamList(parser) {
  24698. const params = [];
  24699. parser.parseLSquare();
  24700. while (!parser.parseOptionalRSquare()) {
  24701. const param = this.parseAllToAllParam(parser);
  24702. params.push(param);
  24703. parser.parseOptionalComma();
  24704. }
  24705. return { value: params };
  24706. }
  24707. parseAllToAllParam(parser) {
  24708. const axes = this.parseAxisRefList(parser);
  24709. parser.parseColon();
  24710. const splitDim = parser.parseInteger();
  24711. parser.parseArrow();
  24712. const concatDim = parser.parseInteger();
  24713. return { axes, splitDim, concatDim };
  24714. }
  24715. parseTensorShardingAttrWrap(parser) {
  24716. return { value: this.parseTensorShardingAttr(parser) };
  24717. }
  24718. parseAxisRefListWrap(parser) {
  24719. return { value: this.parseAxisRefList(parser) };
  24720. }
  24721. parseConstantOp(parser, result) {
  24722. parser.parseOptionalAttrDict(result.attributes);
  24723. const attr = parser.parseDenseElementsAttr();
  24724. result.addAttribute('value', attr.value || attr);
  24725. if (attr.type) {
  24726. if (result.types.length === 0) {
  24727. result.addTypes([attr.type]);
  24728. } else {
  24729. result.types[0] = attr.type;
  24730. }
  24731. }
  24732. return true;
  24733. }
  24734. };
  24735. _.XlaDialect = class extends _.Dialect {
  24736. constructor(operations) {
  24737. super(operations, 'xla');
  24738. }
  24739. parseOperation(parser, result) {
  24740. if (result.op === 'xla.apply_indexing') {
  24741. const indexingMapAttr = parser.parseAttribute();
  24742. result.addAttribute('indexing_map_attr', indexingMapAttr);
  24743. const operands = [];
  24744. if (parser.parseOptionalLParen()) {
  24745. parser.parseOperands(operands);
  24746. parser.parseRParen();
  24747. }
  24748. if (parser.parseOptionalLSquare()) {
  24749. parser.parseOperands(operands);
  24750. parser.parseRSquare();
  24751. }
  24752. const indexType = new _.IndexType();
  24753. for (const operand of operands) {
  24754. parser.resolveOperand(operand, indexType, result.operands);
  24755. }
  24756. parser.parseOptionalAttrDict(result.attributes);
  24757. const map = indexingMapAttr.getIndexingMap().GetAffineMap();
  24758. const numResults = map.getNumResults();
  24759. for (let i = 0; i < numResults; i++) {
  24760. result.addTypes([indexType]);
  24761. }
  24762. return true;
  24763. }
  24764. // xla.loop (%dims)[%ivs] -> (%map_results) in #map iter_args(%args = %inits) -> (types) { body }
  24765. if (result.op === 'xla.loop') {
  24766. const unresolvedDims = [];
  24767. const unresolvedInits = [];
  24768. const regionArgs = [];
  24769. const indexType = new _.IndexType();
  24770. if (parser.parseOptionalLParen()) {
  24771. while (parser.getToken().isNot(_.Token.r_paren)) {
  24772. if (parser.getToken().is(_.Token.percent_identifier)) {
  24773. unresolvedDims.push(parser.parseOperand());
  24774. }
  24775. if (!parser.parseOptionalComma()) {
  24776. break;
  24777. }
  24778. }
  24779. parser.parseRParen();
  24780. }
  24781. // Parse [%ivs] -> (%map_results) - these are block arguments
  24782. if (parser.parseOptionalLSquare()) {
  24783. while (parser.getToken().isNot(_.Token.r_square)) {
  24784. if (parser.getToken().is(_.Token.percent_identifier)) {
  24785. const iv = parser.parseOperand();
  24786. regionArgs.push({ name: iv.name, type: indexType });
  24787. }
  24788. if (!parser.parseOptionalComma()) {
  24789. break;
  24790. }
  24791. }
  24792. parser.parseRSquare();
  24793. }
  24794. if (parser.parseOptionalArrow()) {
  24795. parser.parseLParen();
  24796. while (parser.getToken().isNot(_.Token.r_paren)) {
  24797. if (parser.getToken().is(_.Token.percent_identifier)) {
  24798. const mapResult = parser.parseOperand();
  24799. regionArgs.push({ name: mapResult.name, type: indexType });
  24800. }
  24801. if (!parser.parseOptionalComma()) {
  24802. break;
  24803. }
  24804. }
  24805. parser.parseRParen();
  24806. }
  24807. parser.parseKeyword('in');
  24808. const map = parser.parseAttribute();
  24809. result.addAttribute('indexing_map_attr', map);
  24810. const iterArgNames = [];
  24811. if (parser.parseOptionalKeyword('iter_args')) {
  24812. parser.parseLParen();
  24813. while (parser.getToken().isNot(_.Token.r_paren)) {
  24814. if (parser.getToken().is(_.Token.percent_identifier)) {
  24815. const iterArg = parser.parseOperand();
  24816. iterArgNames.push(iterArg.name);
  24817. }
  24818. if (parser.parseOptionalEqual()) {
  24819. unresolvedInits.push(parser.parseOperand());
  24820. }
  24821. if (!parser.parseOptionalComma()) {
  24822. break;
  24823. }
  24824. }
  24825. parser.parseRParen();
  24826. }
  24827. const resultTypes = [];
  24828. if (parser.parseOptionalArrow()) {
  24829. if (parser.parseOptionalLParen()) {
  24830. const types = parser.parseTypeListNoParens();
  24831. parser.parseRParen();
  24832. for (const t of types) {
  24833. result.addTypes([t]);
  24834. resultTypes.push(t);
  24835. }
  24836. } else {
  24837. const type = parser.parseType();
  24838. result.addTypes([type]);
  24839. resultTypes.push(type);
  24840. }
  24841. }
  24842. for (let i = 0; i < iterArgNames.length; i++) {
  24843. const argType = resultTypes[i] || null;
  24844. regionArgs.push({ name: iterArgNames[i], type: argType });
  24845. }
  24846. for (const dim of unresolvedDims) {
  24847. parser.resolveOperand(dim, indexType, result.operands);
  24848. }
  24849. for (let i = 0; i < unresolvedInits.length; i++) {
  24850. const initType = resultTypes[i] || null;
  24851. parser.resolveOperand(unresolvedInits[i], initType, result.operands);
  24852. }
  24853. if (parser.getToken().is(_.Token.l_brace)) {
  24854. const region = result.addRegion();
  24855. parser.parseRegion(region, regionArgs);
  24856. }
  24857. parser.parseOptionalAttrDict(result.attributes);
  24858. return true;
  24859. }
  24860. return super.parseOperation(parser, result);
  24861. }
  24862. parseAttribute(parser, type) {
  24863. const keyword = parser.parseOptionalKeyword();
  24864. if (keyword === 'indexing_map') {
  24865. return _.IndexingMapAttr.parse(parser, type);
  24866. }
  24867. return null;
  24868. }
  24869. };
  24870. _.XlaGpuDialect = class extends _.Dialect {
  24871. constructor(operations) {
  24872. super(operations, 'xla_gpu');
  24873. }
  24874. parseOperation(parser, result) {
  24875. // xla_gpu.shuffle_reduce(%ops) to N combiner=@func {attrs} : types
  24876. if (result.op === 'xla_gpu.shuffle_reduce') {
  24877. const unresolvedOperands = [];
  24878. if (parser.parseOptionalLParen()) {
  24879. while (parser.getToken().isNot(_.Token.r_paren)) {
  24880. if (parser.getToken().is(_.Token.percent_identifier)) {
  24881. unresolvedOperands.push(parser.parseOperand());
  24882. }
  24883. if (!parser.parseOptionalComma()) {
  24884. break;
  24885. }
  24886. }
  24887. parser.parseRParen();
  24888. }
  24889. parser.parseKeyword('to');
  24890. const maxDistance = parser.getToken().getSpelling().str();
  24891. parser.consumeToken(_.Token.integer);
  24892. result.addAttribute('max_distance', parseInt(maxDistance, 10));
  24893. parser.parseKeyword('combiner');
  24894. parser.parseEqual();
  24895. const combiner = parser.getToken().getSpelling().str();
  24896. parser.consumeToken(_.Token.at_identifier);
  24897. result.addAttribute('combiner', new _.SymbolRefAttr(`@${combiner}`));
  24898. parser.parseOptionalAttrDict(result.attributes);
  24899. if (parser.parseOptionalColon()) {
  24900. const types = parser.parseTypeList();
  24901. parser.resolveOperands(unresolvedOperands, types, result.operands);
  24902. result.addTypes(types);
  24903. } else {
  24904. for (const operand of unresolvedOperands) {
  24905. parser.resolveOperand(operand, null, result.operands);
  24906. }
  24907. }
  24908. return true;
  24909. }
  24910. // xla_gpu.reduce (%inputs) inits(%inits) dimensions=[...] combiner=@func {attrs} : in_types to out_types
  24911. if (result.op === 'xla_gpu.reduce') {
  24912. const unresolvedInputs = [];
  24913. const unresolvedInits = [];
  24914. if (parser.parseOptionalLParen()) {
  24915. while (parser.getToken().isNot(_.Token.r_paren)) {
  24916. if (parser.getToken().is(_.Token.percent_identifier)) {
  24917. unresolvedInputs.push(parser.parseOperand());
  24918. }
  24919. if (!parser.parseOptionalComma()) {
  24920. break;
  24921. }
  24922. }
  24923. parser.parseRParen();
  24924. }
  24925. parser.parseKeyword('inits');
  24926. parser.parseLParen();
  24927. while (parser.getToken().isNot(_.Token.r_paren)) {
  24928. if (parser.getToken().is(_.Token.percent_identifier)) {
  24929. unresolvedInits.push(parser.parseOperand());
  24930. }
  24931. if (!parser.parseOptionalComma()) {
  24932. break;
  24933. }
  24934. }
  24935. parser.parseRParen();
  24936. parser.parseKeyword('dimensions');
  24937. parser.parseEqual();
  24938. const dimensions = parser.parseAttribute();
  24939. result.addAttribute('dimensions', dimensions);
  24940. parser.parseKeyword('combiner');
  24941. parser.parseEqual();
  24942. const combiner = parser.getToken().getSpelling().str();
  24943. parser.consumeToken(_.Token.at_identifier);
  24944. result.addAttribute('combiner', new _.SymbolRefAttr(`@${combiner}`));
  24945. parser.parseOptionalAttrDict(result.attributes);
  24946. if (parser.parseOptionalColon()) {
  24947. const inputTypes = parser.parseTypeList();
  24948. parser.resolveOperands(unresolvedInputs, inputTypes, result.operands);
  24949. parser.parseKeyword('to');
  24950. const outputTypes = parser.parseTypeList();
  24951. result.addTypes(outputTypes);
  24952. parser.resolveOperands(unresolvedInits, outputTypes, result.operands);
  24953. } else {
  24954. for (const input of unresolvedInputs) {
  24955. parser.resolveOperand(input, null, result.operands);
  24956. }
  24957. for (const init of unresolvedInits) {
  24958. parser.resolveOperand(init, null, result.operands);
  24959. }
  24960. }
  24961. return true;
  24962. }
  24963. return super.parseOperation(parser, result);
  24964. }
  24965. };
  24966. _.XTileDialect = class extends _.Dialect {
  24967. constructor(operations) {
  24968. super(operations, 'xtile');
  24969. }
  24970. parseOperation(parser, result) {
  24971. // xtile.entry_func - function-like op with custom format
  24972. if (result.op === 'xtile.entry_func') {
  24973. parser.parseFunctionOp(result, false);
  24974. return true;
  24975. }
  24976. return super.parseOperation(parser, result);
  24977. }
  24978. };
  24979. _.TritonXlaDialect = class extends _.Dialect {
  24980. constructor(operations) {
  24981. super(operations, 'triton_xla');
  24982. // Mark operations with custom directives as having custom assembly format
  24983. this.registerOperandName('triton_xla.extract', { name: 'triton_xla.extract', hasCustomAssemblyFormat: true });
  24984. this.registerOperandName('triton_xla.insert', { name: 'triton_xla.insert', hasCustomAssemblyFormat: true });
  24985. }
  24986. parseOperation(parser, result) {
  24987. // triton_xla.extract from $src as memref<shape, layout> [offsets] [sizes] [strides] : result_type
  24988. if (result.op === 'triton_xla.extract') {
  24989. parser.parseKeyword('from');
  24990. const unresolvedSrc = parser.parseOperand();
  24991. parser.parseKeyword('as');
  24992. // Parse AsMemRefType: memref<shape, layout> - the memref type describes the pointer's layout
  24993. const memrefType = parser.parseType();
  24994. // Extract shape and layout from the memref type
  24995. this._extractMemRefInfo(memrefType, result, 'src_shape', 'src_layout');
  24996. this.parseDynamicIndexList(parser, result, 'offsets', 'static_offsets');
  24997. this.parseDynamicIndexList(parser, result, 'sizes', 'static_sizes');
  24998. this.parseDynamicIndexList(parser, result, 'strides', 'static_strides');
  24999. parser.parseOptionalAttrDict(result.attributes);
  25000. parser.parseColon();
  25001. const resultType = parser.parseType();
  25002. parser.resolveOperand(unresolvedSrc, memrefType, result.operands);
  25003. result.addTypes([resultType]);
  25004. return true;
  25005. }
  25006. // triton_xla.insert $src into $dst as memref<shape, layout> [offsets] [sizes] [strides] : src_type
  25007. if (result.op === 'triton_xla.insert') {
  25008. const unresolvedSrc = parser.parseOperand();
  25009. parser.parseKeyword('into');
  25010. const unresolvedDst = parser.parseOperand();
  25011. parser.parseKeyword('as');
  25012. // Parse AsMemRefType: memref<shape, layout> - the memref type describes the pointer's layout
  25013. const memrefType = parser.parseType();
  25014. // Extract shape and layout from the memref type
  25015. this._extractMemRefInfo(memrefType, result, 'dst_shape', 'dst_layout');
  25016. this.parseDynamicIndexList(parser, result, 'offsets', 'static_offsets');
  25017. this.parseDynamicIndexList(parser, result, 'sizes', 'static_sizes');
  25018. this.parseDynamicIndexList(parser, result, 'strides', 'static_strides');
  25019. parser.parseOptionalAttrDict(result.attributes);
  25020. parser.parseColon();
  25021. const srcType = parser.parseType();
  25022. parser.resolveOperand(unresolvedSrc, srcType, result.operands);
  25023. parser.resolveOperand(unresolvedDst, memrefType, result.operands);
  25024. return true;
  25025. }
  25026. return super.parseOperation(parser, result);
  25027. }
  25028. _extractMemRefInfo(memrefType, op, shapeAttrName, layoutAttrName) {
  25029. // Extract shape and layout from memref type like memref<512x1x128xbf16, #xtile.layout<[2, 1, 0]>>
  25030. const typeStr = memrefType.toString();
  25031. const shapeMatch = typeStr.match(/memref<([\d?x]+)/);
  25032. if (shapeMatch) {
  25033. const dims = shapeMatch[1].split('x').filter((d) => d).map((d) => d === '?' ? -1 : parseInt(d, 10));
  25034. op.addAttribute(shapeAttrName, dims);
  25035. }
  25036. const layoutMatch = typeStr.match(/#[a-z_.]+\.<\[([^\]]+)\]>/);
  25037. if (layoutMatch) {
  25038. const layout = layoutMatch[1].split(',').map((s) => parseInt(s.trim(), 10));
  25039. op.addAttribute(layoutAttrName, layout);
  25040. }
  25041. }
  25042. parseDynamicIndexList(parser, op, dynamicName, staticName) {
  25043. // Parse [val1, val2, ...] where vals can be %ssa or integer constants
  25044. parser.parseLSquare();
  25045. const staticValues = [];
  25046. while (parser.getToken().isNot(_.Token.r_square)) {
  25047. if (parser.getToken().is(_.Token.percent_identifier)) {
  25048. const unresolved = parser.parseOperand();
  25049. parser.resolveOperand(unresolved, null, op.operands);
  25050. staticValues.push(-9223372036854775808n); // ShapedType::kDynamic
  25051. } else if (parser.getToken().is(_.Token.integer)) {
  25052. const value = parser.getToken().getSpelling().str();
  25053. parser.consumeToken(_.Token.integer);
  25054. staticValues.push(BigInt(value));
  25055. }
  25056. if (!parser.parseOptionalComma()) {
  25057. break;
  25058. }
  25059. }
  25060. parser.parseRSquare();
  25061. op.addAttribute(staticName, staticValues);
  25062. }
  25063. };
  25064. _.EnsembleDialect = class extends _.Dialect {
  25065. constructor(operations) {
  25066. super(operations, 'ensemble');
  25067. }
  25068. parseType(parser, dialect) {
  25069. const typeName = parser.parseOptionalKeyword();
  25070. if (!typeName) {
  25071. return null;
  25072. }
  25073. const type = `!${dialect}.${typeName}`;
  25074. const simpleTypes = ['physical_qubit', 'virtual_qubit', 'cbit', 'gate', 'gate_distribution', 'connectivity_graph'];
  25075. if (simpleTypes.includes(typeName)) {
  25076. return new _.Type(type);
  25077. }
  25078. return null;
  25079. }
  25080. };
  25081. _.PolyDialect = class extends _.Dialect {
  25082. constructor(operations) {
  25083. super(operations, 'poly');
  25084. }
  25085. parseType(parser, dialect) {
  25086. const typeName = parser.parseOptionalKeyword();
  25087. if (!typeName) {
  25088. return null;
  25089. }
  25090. let type = `!${dialect}.${typeName}`;
  25091. // poly.poly<N> type has a degree bound parameter
  25092. if (typeName === 'poly' && parser.getToken().is(_.Token.less)) {
  25093. const content = parser.skip('<');
  25094. type += content;
  25095. }
  25096. return new _.Type(type);
  25097. }
  25098. };
  25099. _.NoisyDialect = class extends _.Dialect {
  25100. constructor(operations) {
  25101. super(operations, 'noisy');
  25102. }
  25103. parseType(parser, dialect) {
  25104. if (parser.getToken().is(_.Token.inttype)) {
  25105. const inttype = parser.getToken().getSpelling().str();
  25106. parser.consumeToken(_.Token.inttype);
  25107. return new _.Type(`!${dialect}.${inttype}`);
  25108. }
  25109. const typeName = parser.parseOptionalKeyword();
  25110. if (typeName) {
  25111. let type = `!${dialect}.${typeName}`;
  25112. if (parser.getToken().is(_.Token.less)) {
  25113. type += parser.skip('<');
  25114. }
  25115. return new _.Type(type);
  25116. }
  25117. return null;
  25118. }
  25119. };
  25120. _.XtenNNDialect = class extends _.Dialect {
  25121. constructor(operations) {
  25122. super(operations, 'xten_nn');
  25123. }
  25124. parseAttribute(parser) {
  25125. const keyword = parser.parseOptionalKeyword();
  25126. if (keyword === 'dict_loc') {
  25127. parser.parseLParen();
  25128. const content = parser.skip('(');
  25129. return new _.XtenNNDictLoc(content);
  25130. }
  25131. return null;
  25132. }
  25133. parseOperation(parser, result) {
  25134. if (result.op === 'xten_nn.subgraph') {
  25135. return this.parseSubgraphOp(parser, result);
  25136. }
  25137. if (result.op === 'xten_nn.quantize' || result.op === 'xten_nn.dequantize') {
  25138. return this.parseQuantizeOp(parser, result);
  25139. }
  25140. if (result.op === 'xten_nn.kernel') {
  25141. return this.parseKernelOp(parser, result);
  25142. }
  25143. return super.parseOperation(parser, result);
  25144. }
  25145. // Parse: (%name = %value : type, ...) { body } -> result_types
  25146. // or: (%arg : type, ...) -> result_types (no body)
  25147. parseSubgraphOp(parser, result) {
  25148. const entryArgs = [];
  25149. if (parser.parseOptionalLParen()) {
  25150. while (!parser.parseOptionalRParen()) {
  25151. // Parse either (%name = %value : type) or (%value : type)
  25152. let blockArgName = null;
  25153. let operandRef = null;
  25154. if (parser.getToken().is(_.Token.percent_identifier)) {
  25155. const firstOperand = parser.parseOperand();
  25156. if (parser.parseOptionalEqual()) {
  25157. // (%name = %value : type) form
  25158. blockArgName = firstOperand;
  25159. if (parser.getToken().is(_.Token.percent_identifier)) {
  25160. operandRef = parser.parseOperand();
  25161. }
  25162. } else {
  25163. // (%value : type) form - value is both operand and block arg name
  25164. operandRef = firstOperand;
  25165. blockArgName = firstOperand;
  25166. }
  25167. }
  25168. parser.parseColon();
  25169. const type = parser.parseType();
  25170. if (operandRef) {
  25171. parser.resolveOperands([operandRef], [type], result.operands);
  25172. }
  25173. entryArgs.push({ value: blockArgName, type });
  25174. if (!parser.parseOptionalComma()) {
  25175. if (parser.getToken().is(_.Token.r_paren)) {
  25176. parser.parseOptionalRParen();
  25177. }
  25178. break;
  25179. }
  25180. }
  25181. }
  25182. parser.parseOptionalAttrDictWithKeyword(result.attributes);
  25183. if (parser.getToken().is(_.Token.l_brace)) {
  25184. const region = result.addRegion();
  25185. parser.parseRegion(region, entryArgs, /* enableNameShadowing */ true);
  25186. }
  25187. if (parser.parseOptionalArrow()) {
  25188. const types = parser.getToken().is(_.Token.l_paren) ? parser.parseTypeListParens() : parser.parseTypeListNoParens();
  25189. result.addTypes(types);
  25190. }
  25191. return true;
  25192. }
  25193. // Parse: (%input: type) {attrs} -> type
  25194. parseQuantizeOp(parser, result) {
  25195. if (!parser.parseOptionalLParen()) {
  25196. return false;
  25197. }
  25198. const unresolvedOperands = [];
  25199. while (!parser.parseOptionalRParen()) {
  25200. if (parser.getToken().is(_.Token.percent_identifier)) {
  25201. unresolvedOperands.push(parser.parseOperand());
  25202. }
  25203. parser.parseColon();
  25204. const type = parser.parseType();
  25205. parser.resolveOperands(unresolvedOperands, [type], result.operands);
  25206. unresolvedOperands.length = 0;
  25207. if (!parser.parseOptionalComma()) {
  25208. if (parser.getToken().is(_.Token.r_paren)) {
  25209. parser.parseOptionalRParen();
  25210. }
  25211. break;
  25212. }
  25213. }
  25214. parser.parseOptionalAttrDict(result.attributes);
  25215. result.addTypes(parser.parseArrowTypeList());
  25216. return true;
  25217. }
  25218. // Parse: "name" (%arg : type, ...) instantiation_args [...] {attrs} -> result_types
  25219. parseKernelOp(parser, result) {
  25220. const nameAttr = parser.parseAttribute();
  25221. result.addAttribute('name', nameAttr);
  25222. if (parser.parseOptionalLParen()) {
  25223. const unresolvedOperands = [];
  25224. const types = [];
  25225. while (!parser.parseOptionalRParen()) {
  25226. if (parser.getToken().is(_.Token.percent_identifier)) {
  25227. unresolvedOperands.push(parser.parseOperand());
  25228. }
  25229. parser.parseColon();
  25230. types.push(parser.parseType());
  25231. if (!parser.parseOptionalComma()) {
  25232. if (parser.getToken().is(_.Token.r_paren)) {
  25233. parser.parseOptionalRParen();
  25234. }
  25235. break;
  25236. }
  25237. }
  25238. parser.resolveOperands(unresolvedOperands, types, result.operands);
  25239. }
  25240. if (parser.parseOptionalKeyword('instantiation_args')) {
  25241. const instArgs = [];
  25242. const instArgNames = [];
  25243. if (parser.parseOptionalLSquare()) {
  25244. while (!parser.parseOptionalRSquare()) {
  25245. // Parse either "name" = value or just value
  25246. if (parser.getToken().is(_.Token.string)) {
  25247. const nameOrValue = parser.parseAttribute();
  25248. if (parser.parseOptionalEqual()) {
  25249. // "name" = value form
  25250. instArgNames.push(nameOrValue);
  25251. instArgs.push(parser.parseAttribute());
  25252. } else {
  25253. // Just a string value
  25254. instArgs.push(nameOrValue);
  25255. }
  25256. } else {
  25257. instArgs.push(parser.parseAttribute());
  25258. }
  25259. parser.parseOptionalComma();
  25260. }
  25261. }
  25262. if (instArgs.length > 0) {
  25263. result.addAttribute('instantiation_args', instArgs);
  25264. }
  25265. if (instArgNames.length > 0) {
  25266. result.addAttribute('instantiation_arg_names', instArgNames);
  25267. }
  25268. }
  25269. parser.parseOptionalAttrDict(result.attributes);
  25270. if (parser.parseOptionalArrow()) {
  25271. const types = parser.getToken().is(_.Token.l_paren) ? parser.parseTypeListParens() : parser.parseTypeListNoParens();
  25272. result.addTypes(types);
  25273. }
  25274. return true;
  25275. }
  25276. };
  25277. mlir.Metadata = class {
  25278. static async open(context) {
  25279. if (!mlir.Metadata._metadata) {
  25280. const data = await context.request('mlir-metadata.json');
  25281. mlir.Metadata._metadata = new mlir.Metadata(data);
  25282. }
  25283. return mlir.Metadata._metadata;
  25284. }
  25285. constructor(data) {
  25286. this.operations = new Map();
  25287. if (data) {
  25288. const operations = JSON.parse(data);
  25289. for (const op of operations) {
  25290. const [dialectName] = op.name.split('.');
  25291. if (!this.operations.has(dialectName)) {
  25292. this.operations.set(dialectName, []);
  25293. }
  25294. this.operations.get(dialectName).push(op);
  25295. }
  25296. }
  25297. }
  25298. type(name) {
  25299. const [dialectName] = name.split('.');
  25300. const operations = this.operations.get(dialectName);
  25301. if (operations) {
  25302. const op = operations.find((op) => op.name === name);
  25303. if (op) {
  25304. return op;
  25305. }
  25306. }
  25307. return { name };
  25308. }
  25309. };
  25310. mlir.Error = class extends Error {
  25311. constructor(message) {
  25312. super(message);
  25313. this.name = 'Error loading MLIR model.';
  25314. }
  25315. };
  25316. export const ModelFactory = mlir.ModelFactory;